zoj-3209 Treasure Map【Dancing link x】

B - Treasure Map
Time Limit:2000MS    Memory Limit:32768KB    64bit IO Format:%lld & %llu

Description

Your boss once had got many copies of a treasure map. Unfortunately, all the copies are now broken to many rectangular pieces, and what make it worse, he has lost some of the pieces. Luckily, it is possible to figure out the position of each piece in the original map. Now the boss asks you, the talent programmer, to make a complete treasure map with these pieces. You need to make only one complete map and it is not necessary to use all the pieces. But remember, pieces are not allowed to overlap with each other (See sample 2).

Input

The first line of the input contains an integer T (T <= 500), indicating the number of cases.

For each case, the first line contains three integers nmp (1 <= n,m <= 30, 1 <=p <= 500), the width and the height of the map, and the number of pieces. Thenp lines follow, each consists of four integersx1y1x2y2 (0 <= x1 < x2 <= n, 0 <= y1 <y2 <= m), where (x1, y1) is the coordinate of the lower-left corner of the rectangular piece, and (x2, y2) is the coordinate of the upper-right corner in the original map.

Cases are separated by one blank line.

Output

If you can make a complete map with these pieces, output the least number of pieces you need to achieve this. If it is impossible to make one complete map, just output -1.

Sample Input

3
5 5 1
0 0 5 5

5 5 2
0 0 3 5
2 0 5 5

30 30 5
0 0 30 10
0 10 30 20
0 20 30 30
0 0 15 30
15 0 30 30

Sample Output

1
-1
2

Hint

For sample 1, the only piece is a complete map.

For sample 2, the two pieces may overlap with each other, so you can not make a complete treasure map.

For sample 3, you can make a map by either use the first 3 pieces or the last 2 pieces, and the latter approach one needs less pieces.


刚学完舞蹈链的精确覆盖,就拿这道比较典型的练个手。从头到尾实现一遍。

自己就不赘述了,还是大神讲的好:http://www.cnblogs.com/grenet/p/3145800.html

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define INF 0x3f3f3f3f
#define MAX_N 31
#define MAX_M 31
#define find_min(a,b) a>b?b:a
using namespace std;
struct DLX_node{
	DLX_node *left,*right,*up,*down;
	int column;
};
class DLX
{
public:
	DLX(){
		for(int i=0;i<MAX_N*MAX_M;++i)
		{column[i].column=i;}//列元素的编号编号后就不再更改
	}
	void init(int n,int m);//初始化
	void input(int x1,int y1,int x2,int y2);//数据输入
	void dancing(int times);//递归
	int get_ans(){
		return ans;
	}
private:
	int n,m;
	int ans;
	int count;
	int status_count;
	DLX_node head;
	DLX_node column[MAX_N*MAX_M];//列
	DLX_node table[100000];//数据表,预先开好
	DLX_node *get_dlx_node();
	void init_node(DLX_node *n);
	void insert(DLX_node *l,DLX_node *u,DLX_node *insert_node);
	void remove(DLX_node *c);
	void resume(DLX_node *c);
};
void DLX::init(int n,int m)
{
	this->n=n;
	this->m=m;
	ans=INF;
	status_count=0;
	init_node(&head);
	for(int i=0;i<n*m;++i)
	{
		init_node(column+i);
		insert(&head,column+i,column+i);
	}
}
void DLX::init_node(DLX_node *n)
{
	n->left=n;
	n->right=n;
	n->up=n;
	n->down=n;
}
DLX_node *DLX::get_dlx_node()
{
	init_node(table+status_count);
	return &table[status_count++];
}
void DLX::insert(DLX_node *l,DLX_node *u,DLX_node *insert_node)
{//l为行最左边的元素,u为列最顶端的元素,双向链表的插入
	insert_node->left=l->left;l->left=insert_node;
	insert_node->right=l;insert_node->left->right=insert_node;
	insert_node->up=u->up;u->up=insert_node;
	insert_node->down=u;insert_node->up->down=insert_node;
	insert_node->column=u->column;
}

void DLX::input(int x1,int y1,int x2,int y2)
{
	DLX_node *l=get_dlx_node();
	for(int x=x1;x<x2;++x)
		for(int y=y1;y<y2;++y)
		{
			if(x==x1&&y==y1)
				insert(l,&column[x*m+y],l);
			else insert(l,&column[x*m+y],get_dlx_node());
		}
}
void DLX::remove(DLX_node *c)
{//删除  删除和恢复 是一个出栈和入栈的顺序,这里不开栈了,把顺序翻一转就行了

	//c只需解除左右关系
	c->right->left=c->left;
	c->left->right=c->right;
	for(DLX_node *i=c->down;i!=c;i=i->down)
		for(DLX_node *j=i->right;j!=i;j=j->right)
		{//这里只需要解除上下关系
			j->down->up=j->up;
			j->up->down=j->down;
		}
}
void DLX::resume(DLX_node *c)
{//恢复 与删除顺序相反
	c->right->left=c;
	c->left->right=c;
	for(DLX_node *i=c->up;i!=c;i=i->up)
		for(DLX_node *j=i->right;j!=i;j=j->right)
		{
			j->down->up=j;
			j->up->down=j;
		}
}
void DLX::dancing(int times)
{
	if(head.right==&head)
	{
		ans=find_min(times,ans);
		return;
	}
	//除了列元素,其他元素不动他的左右关系
	DLX_node *c=head.right;
	remove(c);
	for(DLX_node *cur=c->down;cur!=c;cur=cur->down)
	{
		for(DLX_node *col=cur->right;col!=cur;col=col->right)
			remove(column+col->column);
		dancing(times+1);
		for(DLX_node *col=cur->left;col!=cur;col=col->left)
			resume(column+col->column);
	}
	resume(c);
}
DLX dlx;
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int n,m,p;
		scanf("%d%d%d",&n,&m,&p);
		int x1,y1,x2,y2;
		dlx.init(n,m);
		for(int i=0;i<p;++i)
		{
			scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
			dlx.input(x1,y1,x2,y2);
		}
		dlx.dancing(0);
		int ans=dlx.get_ans();
		if(ans==INF)
			printf("-1\n");
		else printf("%d\n",ans);
	}
	return 0;
}


发布了94 篇原创文章 · 获赞 7 · 访问量 5万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章