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. Then p lines follow, each consists of four integers x1y1x2y2 (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
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.
Source
吃午饭回来的路上想明白了这个题怎么做,跳舞链运用的模型是:0.1矩阵选择几行使得新矩阵每列有且只有1个”1“。推广到这个题,要求能够覆盖n*m网格的最少区域数,那就把大区域抽象成行,把每一个小格子看成是列,每读入一个区域,就相当于在原始模型上涂一个点为1,经过递归得到的深度最小值即为解。这个题不要求具体方案,所以返回值是void即可
/*******************
zoj3209
2016.3.1
2628 140
C++ (g++ 4.7.2)
2694
********************/
#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;
const int maxnode = 100010;
const int MaxM = 1010;
const int MaxN = 1010;
int minn;
struct DLX
{
int n,m,size;
int U[maxnode],D[maxnode],R[maxnode],L[maxnode],Row[maxnode],Col[maxnode];
int H[MaxN], S[MaxM];
int ansd, ans[MaxN];
void init(int _n,int _m)
{
n = _n;
m = _m;
for(int i = 0;i <= m;i++)
{
S[i] = 0;
U[i] = D[i] = i;
L[i] = i-1;
R[i] = i+1;
}
R[m] = 0; L[0] = m;
size = m;
for(int i = 1;i <= n;i++)
H[i] = -1;
}
void Link(int r,int c)
{
++S[Col[++size]=c];
Row[size] = r;
D[size] = D[c];
U[D[c]] = size;
U[size] = c;
D[c] = size;
if(H[r] < 0)H[r] = L[size] = R[size] = size;
else
{
R[size] = R[H[r]];
L[R[H[r]]] = size;
L[size] = H[r];
R[H[r]] = size;
}
}
void remove(int c)
{
L[R[c]] = L[c]; R[L[c]] = R[c];
for(int i = D[c];i != c;i = D[i])
for(int j = R[i];j != i;j = R[j])
{
U[D[j]] = U[j];
D[U[j]] = D[j];
--S[Col[j]];
}
}
void resume(int c)
{
for(int i = U[c];i != c;i = U[i])
for(int j = L[i];j != i;j = L[j])
++S[Col[U[D[j]]=D[U[j]]=j]];
L[R[c]] = R[L[c]] = c;
}
//d为递归深度
void Dance(int d)
{
if(d>=ansd&&ansd!=-1) return;
if(R[0] == 0)
{
if(ansd==-1) ansd=d;
else if(d<ansd) ansd=d;
return ;
}
int c = R[0];
for(int i = R[0];i != 0;i = R[i])
if(S[i] < S[c])//只是优化
c = i;
remove(c);
for(int i = D[c];i != c;i = D[i])
{
ans[d] = Row[i];
for(int j = R[i]; j != i;j = R[j])remove(Col[j]);
Dance(d+1);//)return ;
for(int j = L[i]; j != i;j = L[j])resume(Col[j]);
}
resume(c);
}
};
DLX g;
int main()
{
//freopen("cin.txt","r",stdin);
int t,n,m,p;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&m,&p);
g.init(p,n*m);
g.ansd=-1;
for(int i=1;i<=p;i++)//1-p 不是0~p-1!!!
{
int a,b,c,d;
scanf("%d%d%d%d",&a,&b,&c,&d);
for(int j=a+1;j<=c;j++)
for(int k=b+1;k<=d;k++)
g.Link(i,(k-1)*n+j);
}
g.Dance(0);
printf("%d\n",g.ansd);
}
return 0;
}