dlx 精确覆盖
2012-10-11 21:43
176 查看
dlx的合集比赛点击这里
hust
poj 3074 标准数独模版
poj 3076 16*16数独 代码不贴了
hust
poj 3074 标准数独模版
#include <cstdio> #include <cstring> /** 在计算科学理论中,这一类问题的解答被称之为NPC问题中的Hitting Set Problem,中文名应该叫做碰集问题。 该类问题可以通过转换成为精确覆盖问题,其中以行表示概然,以列表示常规约束。 在数独问题中,行所表示的概然状态很明显为(r,c,k)即行,列,放置的数字。而列所表示的约束大致整理了下, 分做四种,即r行中放置数k可行性,c列放置数k可行性,放置于(r,c)格子可行性以及块b(即所属区域)放置数k的可行性。 因此行总共有N*N*N=9*9*9=729个,列总共有9*9*4=324个,问题转化为在729*324的矩阵中取若干行,使每个列只有一个'1', 此时对应一个数独的解,而(r,c)格的约束保证了我们最后解的行数一定<=N*N。至此,模型转化完成。 **/ const int maxn=100000+123; const int maxc=1000+5; int S[maxc], L[maxn], R[maxn], D[maxn], U[maxn]; int H[maxc], ok[maxc], sz, C[maxn], mark[maxn]; ///H是横向的表头, 不知道必不必要 void Link(int row, int col){ S[col]++; C[sz]=col;///C域指向列头 U[sz]=U[col]; D[U[col]]=sz; D[sz]=col; U[col]=sz; if(H[row]==-1)H[row]=L[sz]=R[sz]=sz; else{ L[sz]=L[H[row]]; R[L[H[row]]]=sz; R[sz]=H[row]; L[H[row]]=sz; } mark[sz]=row;/// 标记每个点是哪一行(题目要求输出解属于哪一行) sz++; } void remove(int col) { L[R[col]]=L[col]; R[L[col]]=R[col]; /// 在列对象链表中删除col for (int i=D[col]; i!=col; i=D[i]){/// 删除col列中有1元素的行 for (int j=R[i]; j!=i; j=R[j]){///删除每行的1元素,并修改所在列的S域 U[D[j]]=U[j], D[U[j]]=D[j]; S[C[j]]--; } } } void resume(int col){ for (int i=U[col]; i!=col; i=U[i]){ for (int j=L[i]; j!=i; j=L[j]){ U[D[j]]=j; D[U[j]]=j; S[C[j]]++; }///恢复删除的元素,恢复S域 }///恢复删除的行 L[R[col]]=col; R[L[col]]=col; } bool Dance(int k){ if(R[0]==0){ char ans[100]; for (int i=0; i<k; ++i){ ans[(ok[i]-1)/9]=(ok[i]-1)%9+1+'0'; } ans[k]=0; puts(ans); return true; } int c=R[0]; for(int i=R[0]; i; i=R[i]) if(S[i]<S[c])c=i; remove(c); for(int i=D[c]; i!=c; i=D[i]){ ok[k]=mark[i]; for (int j=R[i]; j!=i; j=R[j]) remove(C[j]); if(Dance(k+1))return true; for (int j=L[i]; j!=i; j=L[j]) resume(C[j]); } resume(c); return false; } void initL(int x){ 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; sz=x+1;///真正的元素从m+1开始 memset (H, -1, sizeof(H)); ///mark每个位置的名字 } const int m=9*9*4; const int n=9*9*9; int main() {/// 1~81:row col 82~162:row k 163~243:col k 244~324:block k char str[100]; while(~scanf("%s", str)){ if(str[0]=='e')break; initL(m); for (int i=0; i<9; ++i){ for (int j=0; j<9; ++j){ int pos=i*9+j; if(str[pos]=='.'){ for (int k=1; k<=9; ++k){ int row=pos*9+k; Link(row, pos+1); int col=81+i*9+k; Link(row, col); col=81*2+j*9+k; Link(row, col); col=81*3+((i/3)*3+j/3)*9+k; Link(row, col); } } else { int k=str[pos]-'0'; int row=pos*9+k; Link(row, pos+1); int col=81+i*9+k; Link(row, col); col=81*2+j*9+k; Link(row, col); col=81*3+((i/3)*3+j/3)*9+k; Link(row, col); } } } Dance(0); } return 0; }
poj 3076 16*16数独 代码不贴了
相关文章推荐
- DLX 舞蹈链 精确覆盖+可重复覆盖
- DLX精确覆盖与重复覆盖模板题
- [DLX精确覆盖] hdu 4210 Su-domino-ku
- ZOJ 3209 Treasure Map (DLX精确覆盖)
- ZOJ 3209 Treasure Map (DLX精确覆盖问题)
- [DLX精确覆盖+打表] hdu 2518 Dominoes
- ZOJ 3290 Treasure Map(DLX+精确覆盖)
- 精确覆盖问题、Algorithm X 与 Dancing Links(DLX)
- (简单) HUST 1017 Exact cover , DLX+精确覆盖。
- (简单) ZOJ 3209 Treasure Map , DLX+精确覆盖。
- HDU 3663 Power Stations DLX精确覆盖
- HDU 2780 Su-Su-Sudoku(数独用DLX精确覆盖求解)
- hdu3111 Sudoku (精确覆盖解数独 DLX)
- 精确覆盖DLX算法模板另一种写法
- [DLX 精确覆盖 模板题] HUST 1017 Exact cover
- DLX (精确覆盖) ZOJ 3209 Treasure Map
- DLX模板之精确覆盖和重复覆盖
- POJ 3074 Sudoku DLX精确覆盖
- [DLX精确覆盖+打表] hdu 2518 Dominoes
- POJ 3076 Sudoku DLX精确覆盖