Dancing links的题目。
具体的dancing links的介绍 看:http://blog.csdn.net/sunny606/article/details/7833551
思想还是好理解的,主要看那个十字链表构成的图,看着看着就能理解。
对于dancing links 得发表一些看法:
1.十字链表 的数组模拟实在太优雅了,美的不行 R[L[x]] = R[x], L[R[x]] = L[x],恢复也优雅。
2.对于搜索这个剪肢 剪得简直是 干干净净,让我感觉对于平时的一些搜索我都可以用双向链表来模拟了
3.实际上这是一个 十字循环链表。
zoj 3209的话,就是一个精确覆盖的问题。把这个图形变成一块一块,然后摊平,5*5的矩阵就能形成25个格子。
然后把题目给的一个一个图形作为行包括的那个小块为1其他为0,就变成了文章中的例题。只要使结果为全1即可,调用dancing links优雅解题。
# include<stdio.h> # include<string.h> # define CL 905 # define ROW 505 # define V 452000 int R[V],L[V]; int U[V],D[V]; int C[V]; int H[ROW],S[CL]; int ak,n,m,size,p; 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) { int i,j; L[R[c]]=L[c]; R[L[c]]=R[c]; for(i=D[c];i!=c;i=D[i]) { for(j=R[i];j!=i;j=R[j]) { S[C[j]]--; U[D[j]]=U[j]; D[U[j]]=D[j]; } } } void resume(int c) { int i,j; for(i=U[c];i!=c;i=U[i]) { for(j=L[i];j!=i;j=L[j]) { S[C[j]]++; U[D[j]]=D[U[j]]=j; } } L[R[c]]=c; R[L[c]]=c; } void Dance(int k) { int i,j,Min,c; if(!R[0]) { if(k<ak) ak=k; return; } for(Min=ROW,i=R[0];i;i=R[i]) if(Min>S[i]) Min=S[i],c=i; remove(c); for(i=D[c];i!=c;i=D[i]) { for(j=R[i];j!=i;j=R[j]) remove(C[j]); Dance(k+1); for(j=L[i];j!=i;j=L[j]) resume(C[j]); } resume(c); } int main() { int i,j,ncase,x1,y1,x2,y2,k; scanf("%d",&ncase); while(ncase--) { scanf("%d%d%d",&n,&m,&p); for(i=0;i<=m*n;i++) { S[i]=0; U[i]=D[i]=i; L[i+1]=i;R[i]=i+1; } R[n*m]=0; size=n*m+1; memset(H,-1,sizeof(H)); for(i=1;i<=p;i++) { scanf("%d%d%d%d",&x1,&y1,&x2,&y2); for(j=y1;j<=y2-1;j++) for(k=x1;k<x2;k++) Link(i,j*n+k+1); } ak=ROW; Dance(0); printf("%d\n",ak==ROW?-1:ak); } return 0; }
zoj 3209 Dancing links/hust 1017,布布扣,bubuko.com
zoj 3209 Dancing links/hust 1017
原文:http://blog.csdn.net/cnh294141800/article/details/20083975