分析:dancing links 裸题 ,只要把每个格子看成一列就好了,精确不重复覆盖问题
#include<cstdio> #include<cstring> #include<queue> #include<cstdlib> #include<algorithm> #include<vector> #include<cmath> using namespace std; typedef long long LL; const int N=500005; const LL mod=1e9+7; int n,m,sz; int u[N],l[N],r[N],d[N]; int col[N],row[N]; int h[505],s[905]; void init() { 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; sz=m; for(int i=1; i<=n; ++i) h[i]=-1; } void link(int x,int y) { ++sz; ++s[y],col[sz]=y,row[sz]=x; u[sz]=u[y],d[u[y]]=sz; d[sz]=y,u[y]=sz; if(h[x]==-1)h[x]=l[sz]=r[sz]=sz; { l[sz]=l[h[x]]; r[l[h[x]]]=sz; r[sz]=h[x]; l[h[x]]=sz; } } void del(int y) { l[r[y]]=l[y]; r[l[y]]=r[y]; for(int i=d[y]; i!=y; 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 y) { for(int i=u[y]; i!=y; i=u[i]) { for(int j=l[i]; j!=i; j=l[j]) { d[u[j]]=u[d[j]]=j; ++s[col[j]]; } } r[l[y]]=l[r[y]]=y; } int ans; void dance(int pos) { if(pos>=ans)return; if(!r[0]) { if(pos<ans)ans=pos; return; } int t=r[0]; for(int i=r[0]; i!=0; i=r[i]) if(s[i]<s[t])t=i; del(t); for(int i=d[t]; i!=t; i=d[i]) { for(int j=r[i]; j!=i; j=r[j]) del(col[j]); dance(pos+1); for(int j=l[i]; j!=i; j=l[j]) resume(col[j]); } resume(t); } int main() { int T,n1,m1,p; scanf("%d",&T); while(T--) { scanf("%d%d%d",&n1,&m1,&p); n=p; m=n1*m1; init(); int x1,x2,y1,y2; for(int i=1; i<=p; ++i) { scanf("%d%d%d%d",&x1,&y1,&x2,&y2); for(int j=x1+1; j<=x2; ++j) for(int k=y1+1; k<=y2; ++k) link(i,(k-1)*n1+j); } ans=505; dance(0); if(ans==505)printf("-1 "); else printf("%d ",ans); } return 0; }