hust 1017( dancing links)
第一道DLX 的题, 算是模板题吧。
看了很久的论文才看懂, 双向十字链表第一次写还是有点纠结。 但是耐心点还是没有问题的。
搜素的优化,感觉这个超高效率的优化应该可以应用在很多方面。 在实现的过程中还有一个需要注意的东西,就是remove 和resume 要对称,不然就可能导致时间很慢或错误。。。
#include <stdio.h> #include <string.h> #include <iostream> using namespace std; #define N 111000 #define INF 0x3fffffff int n,m; int g[1010][1010]; int u[N],d[N],r[N],l[N],c[N],line[N],ans[1010],num[1010]; int head; int tflag; ///////////// int tg[1010][1010]; int why=0; void remove(int s) { why++; r[l[s]]=r[s]; l[r[s]]=l[s]; for(int i=d[s];i!=s;i=d[i]) { for(int j=r[i];j!=i;j=r[j]) { num[c[j]]--; u[d[j]]=u[j]; d[u[j]]=d[j]; } } } void resume(int s) { why++; r[l[s]]=s; l[r[s]]=s; for(int i=u[s];i!=s;i=u[i]) { for(int j=l[i];j!=i;j=l[j]) { num[c[j]]++; u[d[j]]=j; d[u[j]]=j; } } } void print() { memset(tg,0,sizeof(tg)); for(int i=r[head];i!=head;i=r[i]) { for(int j=d[i];j!=i;j=d[j]) { tg[line[j]][c[j]]=1; } } for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) printf("%d ",tg[i][j]); printf("\n"); } } int dfs(int s) { if(tflag==1) return 1; if(r[head]==head) { tflag=1; printf("%d ",s); for(int i=0;i<s;i++) printf("%d ",ans[i]); return 1; } int mi=INF; int u1; for(int i=r[head];i!=head;i=r[i]) { if(num[i]< mi) { mi=num[i]; u1=i; } } remove(u1); //print(); for(int i=d[u1];i!=u1;i=d[i]) { ans[s] = line[i]; for(int j=r[i];j!=i;j=r[j]) { remove(c[j]); //print(); } if( dfs(s+1) == 1 ) return 1; for(int j=l[i];j!=i;j=l[j]) resume(c[j]); } resume(u1); // 回复时与顺序无关... return 0; } int main() { while(scanf("%d%d",&n,&m)!=EOF) { tflag=0; memset(ans,-1,sizeof(ans)); memset(g,-1,sizeof(g)); int id=1; head=0; r[0]=0; l[0]=0; int tmp=0; for(int i=1;i<=m;i++) { c[id]=i; l[id]=tmp; r[id]=r[tmp]; r[tmp]=id; l[head]=id; tmp=id; id++; } for(int i=1;i<=n;i++) { int thead=-1; int cnt; scanf("%d",&cnt); tmp=-1; for(int j=0;j<cnt;j++) { int pos; scanf("%d",&pos); g[i][pos]=id; line[id]=i; if(thead==-1) { thead=id; tmp=id; l[tmp]=tmp; r[tmp]=tmp; } else { l[id]=tmp; r[id]=r[tmp]; r[tmp]=id; l[thead]=id; tmp=id; } tmp=id; id++; } } /////////////////////// for(int j=1; j<=m ;j++) { int tcnt=0; int thead=j; int tid; u[thead]=thead; d[thead]=thead; tmp=thead; for(int i=1 ; i<=n ; i++) { if(g[i][j]!=-1) { tcnt++; tid=g[i][j]; u[tid]=tmp; d[tid]=d[tmp]; d[tmp]=tid; u[thead]=tid; tmp=tid; c[tid]=j; } } num[j]=tcnt; // 这一列有多少元素... } ///////////////////////// int flag = dfs(0); if(flag==0) printf("NO\n"); else { printf("\n"); } printf("why=%d\n",why); } return 0; }