POJ 1084
WA了好久,第一次用重覆盖的模型做题。感觉这题有个陷阱,那就是当去掉某些边后,若因为这个边去掉而被破环的正方形还存在,那么就会造成覆盖不完全,WA.
所以,在去掉边后,必定有些正方形是不存在的,须重新计算。另外,计算一个正方形有哪些边也很困难。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int Maxn=100; const int Maxr=100; const int Maxnode=10000; const int inf=(1<<30); bool vis[Maxn]; bool ls[Maxr][Maxn]; int L[Maxnode], R[Maxnode], D[Maxnode], U[Maxnode], C[Maxnode]; int S[Maxn], H[Maxr], size; //²»ÐèÒªSÓò void Link(int r, int c) { S[c]++; C[size]=c; U[size]=U[c]; D[U[c]]=size; D[size]=c; U[c]=size; if(H[r]==-1) H[r]=L[size]=R[size]=size; else { L[size]=L[H[r]]; R[L[H[r]]]=size; R[size]=H[r]; L[H[r]]=size; } size++; } void remove(int c){ for (int i=D[c]; i!=c; i=D[i]) L[R[i]]=L[i], R[L[i]]=R[i]; } void resume(int c){ for (int i=U[c]; i!=c; i=U[i]) L[R[i]]=R[L[i]]=i; } int h(){ //Óþ«È·¸²¸ÇÈ¥¹ÀËã¼ôÖ¦ int ret=0; bool vist[Maxn]; memset (vist, false, sizeof(vist)); for (int i=R[0]; i; i=R[i]) { if(vist[i])continue; ret++; vist[i]=true; for (int j=D[i]; j!=i; j=D[j]) for (int k=R[j]; k!=j; k=R[k]) vist[C[k]]=true; } return ret; } int ans; void Dance(int k){ //¸ù¾Ý¾ßÌåÎÊÌâÑ¡ÔñÏÞÖÆËÑË÷Éî¶È»òÖ±½ÓÇó½â¡£ if(k+h()>=ans) return; if(!R[0]){ if(k<ans)ans=k; return; } int c=R[0]; for (int i=R[0]; i; i=R[i]) if(S[i]<S[c])c=i; for (int i=D[c]; i!=c; i=D[i]){ remove(i); for (int j=R[i]; j!=i; j=R[j]) remove(j); Dance(k+1); for (int j=L[i]; j!=i; j=L[j]) resume(j); resume(i); } return ; } void initL(int x){ //col is 1~x,row start from 1 for (int i=0; i<=x; ++i){ S[i]=0; D[i]=U[i]=i; L[i+1]=i; R[i]=i+1; } //¶ÔÁбíÍ·³õʼ»¯ R[x]=0; size=x+1; //ÕæÕýµÄÔªËØ´Óm+1¿ªÊ¼ memset (H, -1, sizeof(H)); ans=inf; //markÿ¸öλÖõÄÃû×Ö } bool check(int i,int j,int si,int n){ for(int k=0;k<si;k++){ if(vis[(i-1)*(2*n+1)+j+k]) return false; if(vis[(i-1+si)*(2*n+1)+j+k]) return false; if(vis[i*n+(i-1)*(n+1)+j+k*(2*n+1)]) return false; if(vis[i*n+(i-1)*(n+1)+j+k*(2*n+1)+si]) return false; } return true; } int main(){ int kase,n; int sof,tmp,tt,c; scanf("%d",&kase); while(kase--){ // sof=0; scanf("%d",&n); // initL(sof); scanf("%d",&tt); memset(vis,false,sizeof(vis)); for(int i=1;i<=tt;i++){ scanf("%d",&tmp); vis[tmp]=true; } memset(ls,false,sizeof(ls)); c=1; for(int si=1;si<=n;si++){ for(int i=1;i<=n-si+1;i++){ for(int j=1;j<=n-si+1;j++){ if(check(i,j,si,n)){ for(int k=0;k<si;k++){ ls[(i-1)*(2*n+1)+j+k][c]=true; ls[(i-1+si)*(2*n+1)+j+k][c]=true; ls[i*n+(i-1)*(n+1)+j+k*(2*n+1)][c]=true; ls[i*n+(i-1)*(n+1)+j+k*(2*n+1)+si][c]=true; } c++; } } } } initL(c-1); for(int i=1;i<=2*(n)*(n+1);i++){ for(int j=1;j<c;j++) if(ls[i][j]) Link(i,j); } Dance(0); printf("%d\n",ans); } return 0; }