BZOJ1501: [NOI2005]智慧珠游戏
精确覆盖问题,用dancing links求解。
打常量表比较麻烦。
const int f[60][12]={ 0,3,0,0,0,1,1,0,0,0,0,0, 0,3,0,0,0,1,1,1,0,0,0,0, 0,3,0,0,1,0,1,1,0,0,0,0, 0,3,0,1,1,0,1,1,0,0,0,0, 1,4,0,0,0,1,0,2,0,3,0,0, 1,4,0,0,1,0,2,0,3,0,0,0, 2,4,0,0,0,1,0,2,1,0,0,0, 2,4,0,0,0,1,0,2,1,2,0,0, 2,4,0,0,0,1,1,0,2,0,0,0, 2,4,0,0,0,1,1,1,2,1,0,0, 2,4,0,0,1,0,1,1,1,2,0,0, 2,4,0,0,1,0,2,0,2,1,0,0, 2,4,0,1,1,1,2,0,2,1,0,0, 2,4,0,2,1,0,1,1,1,2,0,0, 3,4,0,0,0,1,1,0,1,1,0,0, 4,5,0,0,0,1,0,2,1,0,2,0, 4,5,0,0,0,1,0,2,1,2,2,2, 4,5,0,0,1,0,2,0,2,1,2,2, 4,5,0,2,1,2,2,0,2,1,2,2, 5,5,0,0,0,1,0,2,0,3,1,1, 5,5,0,0,0,1,0,2,0,3,1,2, 5,5,0,0,1,0,1,1,2,0,3,0, 5,5,0,0,1,0,2,0,2,1,3,0, 5,5,0,1,1,0,1,1,1,2,1,3, 5,5,0,1,1,0,1,1,2,1,3,1, 5,5,0,1,1,1,2,0,2,1,3,1, 5,5,0,2,1,0,1,1,1,2,1,3, 6,5,0,0,0,1,0,2,1,0,1,2, 6,5,0,0,0,1,1,0,2,0,2,1, 6,5,0,0,0,1,1,1,2,0,2,1, 6,5,0,0,0,2,1,0,1,1,1,2, 7,5,0,0,0,1,0,2,1,0,1,1, 7,5,0,0,0,1,0,2,1,1,1,2, 7,5,0,0,0,1,1,0,1,1,1,2, 7,5,0,0,0,1,1,0,1,1,2,0, 7,5,0,0,0,1,1,0,1,1,2,1, 7,5,0,0,1,0,1,1,2,0,2,1, 7,5,0,1,0,2,1,0,1,1,1,2, 7,5,0,1,1,0,1,1,2,0,2,1, 8,5,0,0,0,1,0,2,1,2,1,3, 8,5,0,0,0,1,1,1,1,2,1,3, 8,5,0,0,1,0,1,1,2,1,3,1, 8,5,0,0,1,0,2,0,2,1,3,1, 8,5,0,1,0,2,0,3,1,0,1,1, 8,5,0,1,1,0,1,1,2,0,3,0, 8,5,0,1,1,1,2,0,2,1,3,0, 8,5,0,2,0,3,1,0,1,1,1,2, 9,5,0,1,1,0,1,1,1,2,2,1, 10,5,0,0,0,1,1,1,1,2,2,2, 10,5,0,0,1,0,1,1,2,1,2,2, 10,5,0,1,0,2,1,0,1,1,2,0, 10,5,0,2,1,1,1,2,2,0,2,1, 11,5,0,0,0,1,0,2,0,3,1,0, 11,5,0,0,0,1,0,2,0,3,1,3, 11,5,0,0,0,1,1,0,2,0,3,0, 11,5,0,0,0,1,1,1,2,1,3,1, 11,5,0,0,1,0,1,1,1,2,1,3, 11,5,0,0,1,0,2,0,3,0,3,1, 11,5,0,1,1,1,2,1,3,0,3,1, 11,5,0,3,1,0,1,1,1,2,1,3 }; #include<cstdio> #include<cstdlib> #include<new> #define FOR(i,s,t)\ for(ptr i=(s)->t;i!=(s);i=i->t) const int N=3300; const int M=67; char s[16][16]; int q[M],v[12]; typedef struct node*ptr; struct node{ ptr l,r,u,d; int x,y; node(){l=r=u=d=this;} node(ptr i,ptr j){ l=i,r=i->r,u=j,d=j->d; x=i->x,++q[y=j->y]; l->r=r->l=u->d=d->u=this; } }e[N*6],r[N],c[M]; ptr o=e+1,h=e,t=e; int cal(int i,int j){return i*(i+1)/2+j;} int xpos(int k){ for(int i=1;;++i) if(i*(i+1)/2>k)return i-1; } int ypos(int k){ return k-xpos(k)*(xpos(k)+1)/2; } void ins(int i,int j,int k){ int s=k*55+cal(i,j); new(o++)node(r+s,c+*f[k]+55); for(int l=1;l<=f[k][1];++l) new(o++)node(r+s,c+cal(i+f[k][l*2],j+f[k][l*2+1])); } void rem(int k){ c[k].l->r=c[k].r,c[k].r->l=c[k].l; FOR(i,c+k,d)FOR(j,i,l) j->u->d=j->d,j->d->u=j->u,--q[j->y]; } void res(int k){ c[k].r->l=c[k].l->r=c+k; FOR(i,c+k,u)FOR(j,i,l) ++q[(j->u->d=j->d->u=j)->y]; } void dfs(int z){ static int u[12]; if(h->l==h){ for(int a=0;a!=12;++a){ int i=xpos(u[a]%55); int j=ypos(u[a]%55); int k=u[a]/55; for(int l=1;l<=f[k][1];++l) s[f[k][l*2]+i][f[k][l*2+1]+j]=*f[k]+65; } for(int i=0;i!=10;++i)puts(s[i]); exit(0); } int s=h->l->y; FOR(i,h,l) if(q[s]>q[i->y])s=i->y; rem(s); FOR(i,c+s,d){ u[z]=i->x; FOR(j,i,r)rem(j->y); dfs(z+1); FOR(j,i,l)res(j->y); } res(s); } bool jud(const int*f,int i,int j,int k){ for(int l=1;l<=f[1];++l) if(s[f[l*2]+i][f[l*2+1]+j]!=k)return 0; return 1; } int main(){ for(int i=0;i!=10;++i){ scanf("%s",s[i]); for(int j=0;s[i][j];++j) if(s[i][j]!=46)v[s[i][j]-65]=1; } for(int i=0;i!=N;++i) (t=((t->d=r+i)->u=t)->d)->x=i; t=((t->d=h)->u=t)->d; for(int i=M-1;~i;--i) (t=((t->l=c+i)->r=t)->l)->y=i; t=((t->l=h)->r=t)->l; for(int i=0;i!=10;++i) for(int j=0;s[i][j];++j) for(int k=0;k!=60;++k) if(jud(f[k],i,j,v[*f[k]]?*f[k]+65:46))ins(i,j,k); for(int i=0;i!=N;++i) r[i].l->r=r[i].r,r[i].r->l=r[i].l; dfs(0),puts("No solution"); }