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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章