HDU - 1603 A Puzzling Problem (Dance Link 精確覆蓋問題)
阿新 • • 發佈:2019-01-02
題意:
給定幾個方塊,看是否能拼成4*4的形狀,這些方塊不能旋轉,翻轉,如果能拼成,輸出拼成後的圖形(任意一個)。
分析:
可以用dfs進行搜尋填圖,但是自我感覺dance link寫起來更為簡單。
但要注意存圖跟建圖,儲存舞蹈鏈每行對應得起點座標,以及長寬,對應得編號,便於輸出。還有dance函式裡面要記得判斷該拼塊用過就不能再使用了。
#include<bits/stdc++.h> using namespace std; const int maxn=10000; bool vis[6]; int puzzle[5][5],tmp[6][5][5],to[200][5]; struct DLX{ int n,m,size; int U[maxn],D[maxn],R[maxn],L[maxn],Row[maxn],Col[maxn]; int H[maxn],S[maxn]; 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; } } inline 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; } bool dance(int d){ if(R[0]==0){ ansd=d; return true; } 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]){ if(vis[to[Row[i]][0]]) continue; vis[to[Row[i]][0]]=1; ans[d]=Row[i]; for(int j=R[i];j!=i;j=R[j]) remove(Col[j]); if(dance(d+1)) return true; vis[to[Row[i]][0]]=0; for(int j=L[i];j!=i;j=L[j]) resume(Col[j]); } resume(c); return false; } bool solve(vector<int> &v){ v.clear(); if(!dance(0)) return false; for(int i=0;i<ansd;i++){ v.push_back(ans[i]); } return true; } }; DLX dlx; int main(){ int n; while(scanf("%d",&n),n){ dlx.init(200,16); int o=0,num=0; while(n--){ int r,c; scanf("%d%d",&r,&c); num++; for(int i=0;i<r;i++){ for(int j=0;j<c;j++){ char ch; scanf(" %c",&ch); tmp[num][i][j]=ch-'0'; } } for(int i=0;i+r<=4;i++){ for(int j=0;j+c<=4;j++){ o++; to[o][0]=num; to[o][1]=i; to[o][2]=j; to[o][3]=r; to[o][4]=c; for(int x=i;x<i+r;x++){ for(int y=j;y<j+c;y++){ if(tmp[num][x-i][y-j]) dlx.Link(o,x*4+y+1); } } } } } memset(vis,0,sizeof vis); vector<int> ans; if(!dlx.solve(ans)){ printf("No solution possible\n"); }else{ for(int i=0;i<ans.size();i++){ int o=ans[i]; int r=to[o][1],c=to[o][2]; for(int x=r;x<r+to[o][3];x++){ for(int y=c;y<c+to[o][4];y++){ if(tmp[to[o][0]][x-r][y-c]) puzzle[x][y]=to[o][0]; } } } for(int i=0;i<4;i++){ for(int j=0;j<4;j++){ printf("%d",puzzle[i][j]); } printf("\n"); } } printf("\n"); } return 0; }