一片区域从0 0到 n,m,现有若干个矩形碎片,问最少需要多少个碎片可以不重复的覆盖这片区域。
第一道要自己建模型的题..把格点编号,看做矩阵的列,把每个碎片的编号看成行,这样可以转化成01矩阵中选若干行使得每一列恰有一个1的问题,建好表之后跑一遍DLX就行。因为这题是一行一行的添加的,所以可以省去每行的表头,这么小效率可能会高一点...
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
int n,m,anss,k,num;
int nn,mm;
const int inf=(1<<29);
const int maxx=610;
const int maxy=1010;
const int maxn=610*1010;
int col[maxn],row[maxn],ans[maxn];
int S[maxy];
int size;
int U[maxn],D[maxn],L[maxn],R[maxn];
struct DLX
{
int tail,head;
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)
{
L[R[c]]=c;
R[L[c]]=c;
for (int i=U[c]; i!=c; i=U[i])
{
for (int j=L[i]; j!=i; j=L[j])
{
U[D[j]]=j;
D[U[j]]=j;
++S[col[j]];
}
}
}
bool dfs(int k)
{
if (k>=anss) return false;
int c=R[0];
if (c==0)
{
anss=k;
return true;
}
for (int i=R[0]; i!=0; i=R[i])
{
if (S[c]>S[i]) c=i;
}
remove(c);
for (int i=D[c]; i!=c; i=D[i])
{
ans[k]=row[i];
for (int j=R[i]; j!=i; j=R[j]) remove(col[j]);
dfs(k+1);
for (int j=L[i]; j!=i; j=L[j]) resume(col[j]);
}
resume(c);
return false;
}
void init(int m)
{
int x1,x2,y1,y2;
for (int i=0; i<=m; i++)
{
S[i]=0;
L[i]=i-1;
R[i]=i+1;
U[i]=D[i]=i;
}
L[0]=m;
R[m]=0;
size=m+1;
for (int i=1; i<=k; i++)
{
head=tail=size;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
for (int x=x1; x<x2; x++)
for (int y=y1; y<y2; y++)
{
int pos=y*nn+x+1;
++S[col[size]=pos];
U[D[pos]]=size;
D[size]=D[pos];
U[size]=pos;
D[pos]=size;
R[size]=tail; L[tail]=size;
L[size]=head; R[head]=size;
tail=size;
size++;
}
}
}
}dlx;
int main()
{
// freopen("in.txt","r",stdin);
int tt;
scanf("%d",&tt);
while(tt--)
{
anss=inf;
scanf("%d%d%d",&nn,&mm,&k);
n=k;
m=(nn)*(mm);
// int spc=0;
// for (int i=0; i<nn; i++)
// for (int j=0; j<mm; j++)
// g[i][j]=++spc;
dlx.init(m);
bool bad=false;
for (int i=1; i<=m; i++)
if (!S[i])
{
bad=true;
break;
}
if (bad)
{
puts("-1");
continue;
}
dlx.dfs(0);
if (anss<inf)
{
printf("%d\n",anss);
}
else
{
puts("-1");
}
}
return 0;
}