POJ 3074,3076,2676 数独 Dancing Links舞蹈链
来源:互联网 发布:各种手游刷元宝软件 编辑:程序博客网 时间:2024/04/26 19:42
POJ 3074 Sudoku
思路:数独正好是精确覆盖问题的最好例子,这个也算是舞蹈链的模板了吧。
这个和网络流一样,难的是建模。如果能想好怎么建立矩阵的话,那一切都容易了。
这题怎么建矩阵,可以看论文:http://www.cnblogs.com/steady/archive/2011/03/15/1984791.html
#pragma comment(linker, "/STACK:1024000000,1024000000")#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<map>#include<queue>#include<set>#include<cmath>#include<bitset>#define mem(a,b) memset(a,b,sizeof(a))#define lson i<<1,l,mid#define rson i<<1|1,mid+1,r#define llson j<<1,l,mid#define rrson j<<1|1,mid+1,r#define INF 0x7fffffff#define maxn 1000005typedef long long ll;typedef unsigned long long ull;using namespace std;int head,sz;int U[maxn],D[maxn],L[maxn],R[maxn];//上下左右链表指针int H[maxn],ROW[maxn],C[maxn],S[maxn],O[maxn];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[C[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[C[j]]; U[D[j]]=j; D[U[j]]=j; } } L[R[c]]=c; R[L[c]]=c;}void init(int m)//m是列{ head=0;//头指针为0 for(int i=0; i<=m; i++) { U[i]=i; D[i]=i;//建立双向十字链表 L[i]=i-1; R[i]=i+1; S[i]=0; } R[m]=0; L[0]=m; S[0]=INF+1; sz=m+1; memset(H,0,sizeof(H));}void insert(int i, int j){ if(H[i]) { L[sz] = L[H[i]]; R[sz] = H[i]; L[R[sz]] = sz; R[L[sz]] = sz; } else { L[sz] = sz; R[sz] = sz; H[i] = sz; } U[sz] = U[j]; D[sz] = j; U[D[sz]] = sz; D[U[sz]] = sz; C[sz] = j; ROW[sz] = i; ++S[j]; ++sz;}bool dfs(int k,int len){ if(R[head]==head) { sort(O,O+len*len); int p=0; for(int i=0; i<len; i++) for(int j=0; j<len; j++) { int num=O[p++]; num=num-(i*len+j)*len; printf("%d",num); } puts(""); return true; } int s=INF,c; for (int t=R[head]; t!=head; t=R[t]) if (S[t]<s) s=S[t],c=t; remove(c); for(int i=D[c]; i!=c; i=D[i]) { O[k]=ROW[i]; for(int j=R[i]; j!=i; j=R[j]) remove(C[j]); if(dfs(k+1,len)) return true; for(int j=L[i]; j!=i; j=L[j]) resume(C[j]); } resume(c); return false;}void calc(int i,int j,int k,int len){ int r=(i*len+j-1)*len+k; int base=sqrt(len); //第i行有数字k insert(r,i*len+k); //第j列有数字k insert(r,len*len+(j-1)*len+k); //第k块有数字k int block=(j-1)/base*base+i/base; insert(r,len*len*2+block*len+k); //第i行j列有一个数字(限制一个出格子只填一个数) insert(r,len*len*3+i*len+j);}void build(char *s,int len)//len表示是几宫数独{ int i,j,k,p=0; init(len*len*4); for(i=0; i<len; i++) for(j=1; j<=len; j++,p++) { if(s[p]=='.') for(k=1; k<=len; k++) calc(i,j,k,len); else calc(i,j,s[p]-'0',len); }}int main(){ //freopen("1.txt","r",stdin); char s[84]; while(scanf("%s",s)&&strcmp(s,"end")) { build(s,9); dfs(0,9);//从根开始搜 } return 0;}
poj 3076 Sudoku
#pragma comment(linker, "/STACK:1024000000,1024000000")#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<map>#include<queue>#include<set>#include<cmath>#include<bitset>#define mem(a,b) memset(a,b,sizeof(a))#define lson i<<1,l,mid#define rson i<<1|1,mid+1,r#define llson j<<1,l,mid#define rrson j<<1|1,mid+1,r#define INF 0x7fffffff#define maxn 1000005typedef long long ll;typedef unsigned long long ull;using namespace std;int head,sz;int U[maxn],D[maxn],L[maxn],R[maxn];//上下左右链表指针int H[maxn],ROW[maxn],C[maxn],S[maxn],O[maxn];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[C[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[C[j]]; U[D[j]]=j; D[U[j]]=j; } } L[R[c]]=c; R[L[c]]=c;}void init(int m)//m是列{ head=0;//头指针为0 for(int i=0; i<=m; i++) { U[i]=i; D[i]=i;//建立双向十字链表 L[i]=i-1; R[i]=i+1; S[i]=0; } R[m]=0; L[0]=m; S[0]=INF+1; sz=m+1; memset(H,0,sizeof(H));}void insert(int i, int j){ if(H[i]) { L[sz] = L[H[i]]; R[sz] = H[i]; L[R[sz]] = sz; R[L[sz]] = sz; } else { L[sz] = sz; R[sz] = sz; H[i] = sz; } U[sz] = U[j]; D[sz] = j; U[D[sz]] = sz; D[U[sz]] = sz; C[sz] = j; ROW[sz] = i; ++S[j]; ++sz;}bool dfs(int k,int len){ if(R[head]==head) { sort(O,O+len*len); int p=0; for(int i=0; i<len; i++) { for(int j=0; j<len; j++) { int num=O[p++]; num=num-(i*len+j)*len; printf("%c",num+'A'-1); } puts(""); } puts(""); return true; } int s=INF,c; for (int t=R[head]; t!=head; t=R[t]) if (S[t]<s) s=S[t],c=t; remove(c); for(int i=D[c]; i!=c; i=D[i]) { O[k]=ROW[i]; for(int j=R[i]; j!=i; j=R[j]) remove(C[j]); if(dfs(k+1,len)) return true; for(int j=L[i]; j!=i; j=L[j]) resume(C[j]); } resume(c); return false;}void calc(int i,int j,int k,int len){ int r=(i*len+j-1)*len+k; int base=sqrt(len); //第i行有数字k insert(r,i*len+k); //第j列有数字k insert(r,len*len+(j-1)*len+k); //第k块有数字k int block=(j-1)/base*base+i/base; insert(r,len*len*2+block*len+k); //第i行j列有一个数字(限制一个出格子只填一个数) insert(r,len*len*3+i*len+j);}void build(char s[][17],int len)//len表示是几宫数独{ int i,j,k; init(len*len*4); for(i=0; i<len; i++) for(j=1; j<=len; j++) { if(s[i][j-1]=='-') for(k=1; k<=len; k++) calc(i,j,k,len); else calc(i,j,s[i][j-1]-'A'+1,len); }}int main(){ //freopen("1.txt","r",stdin); char s[17][17]; while(~scanf("%s",s[0])) { for(int i=1; i<16; i++) scanf("%s",s[i]); build(s,16); dfs(0,16);//从根开始搜 } return 0;}
POJ 2676 Sudoku
#pragma comment(linker, "/STACK:1024000000,1024000000")#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<map>#include<queue>#include<set>#include<cmath>#include<bitset>#define mem(a,b) memset(a,b,sizeof(a))#define lson i<<1,l,mid#define rson i<<1|1,mid+1,r#define llson j<<1,l,mid#define rrson j<<1|1,mid+1,r#define INF 0x7fffffff#define maxn 1000005typedef long long ll;typedef unsigned long long ull;using namespace std;int head,sz;int U[maxn],D[maxn],L[maxn],R[maxn];//上下左右链表指针int H[maxn],ROW[maxn],C[maxn],S[maxn],O[maxn];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[C[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[C[j]]; U[D[j]]=j; D[U[j]]=j; } } L[R[c]]=c; R[L[c]]=c;}void init(int m)//m是列{ head=0;//头指针为0 for(int i=0; i<=m; i++) { U[i]=i; D[i]=i;//建立双向十字链表 L[i]=i-1; R[i]=i+1; S[i]=0; } R[m]=0; L[0]=m; S[0]=INF+1; sz=m+1; memset(H,0,sizeof(H));}void insert(int i, int j){ if(H[i]) { L[sz] = L[H[i]]; R[sz] = H[i]; L[R[sz]] = sz; R[L[sz]] = sz; } else { L[sz] = sz; R[sz] = sz; H[i] = sz; } U[sz] = U[j]; D[sz] = j; U[D[sz]] = sz; D[U[sz]] = sz; C[sz] = j; ROW[sz] = i; ++S[j]; ++sz;}bool dfs(int k,int len){ if(R[head]==head) { sort(O,O+len*len); int p=0; for(int i=0; i<len; i++) { for(int j=0; j<len; j++) { int num=O[p++]; num=num-(i*len+j)*len; printf("%d",num); } puts(""); } return true; } int s=INF,c; for (int t=R[head]; t!=head; t=R[t]) if (S[t]<s) s=S[t],c=t; remove(c); for(int i=D[c]; i!=c; i=D[i]) { O[k]=ROW[i]; for(int j=R[i]; j!=i; j=R[j]) remove(C[j]); if(dfs(k+1,len)) return true; for(int j=L[i]; j!=i; j=L[j]) resume(C[j]); } resume(c); return false;}void calc(int i,int j,int k,int len){ int r=(i*len+j-1)*len+k; int base=sqrt(len); //第i行有数字k insert(r,i*len+k); //第j列有数字k insert(r,len*len+(j-1)*len+k); //第k块有数字k int block=(j-1)/base*base+i/base; insert(r,len*len*2+block*len+k); //第i行j列有一个数字(限制一个出格子只填一个数) insert(r,len*len*3+i*len+j);}void build(char s[][10],int len)//len表示是几宫数独{ int i,j,k; init(len*len*4); for(i=0; i<len; i++) for(j=1; j<=len; j++) { if(s[i][j-1]=='0') for(k=1; k<=len; k++) calc(i,j,k,len); else calc(i,j,s[i][j-1]-'0',len); }}int main(){ //freopen("1.txt","r",stdin); int t; cin>>t; while(t--) { char s[10][10]; for(int i=0; i<9; i++) scanf("%s",s[i]); build(s,9); dfs(0,9);//从根开始搜 } return 0;}
0 0
- POJ 3074,3076,2676 数独 Dancing Links舞蹈链
- POJ 2676 3074 3076 数独3题 Dancing Links
- 【Dancing Links舞蹈链】poj 3076 Sudoku
- POJ 2676 数独 Dancing-Links(DLX)
- poj 3074/3076 数独(Dancing Links)
- 算法实践——舞蹈链(Dancing Links)算法求解数独
- 【DLX】【vijos P1345】【codevs1174】舞蹈链(Dancing Links)——数独问题
- dancing links 算法学习小记 Poj 3074 Sudoku (数独)
- POJ 3074 Sudoku(数独|Dancing Links精确覆盖)
- poj3074 & 3076 数独 Dancing Links
- poj3074/3076 Dancing Links (数独)
- dancing links(舞蹈链)
- 舞蹈链模板 Dancing Links
- dancing links - 舞蹈的链表
- 舞蹈链(Dancing Links)算法
- Sudoku 数独 Dancing Links模板
- hdu 4069(Dancing Links数独)
- dancing links-数独的程序解决方案
- GNU gcc 和 g++ 的区别详解
- JBOSS部署JavaEE项目方法及环境变量配置_JAVA_HOME-JBOSS_HOME
- STL remove和erase
- 自动托管转为提供商托管/跨域访问
- Windows 9, Threshold ,概念版 ,预览版
- POJ 3074,3076,2676 数独 Dancing Links舞蹈链
- Ubuntu14.04 gedit 打开windows下txt乱码问题
- PHP 过滤html标签的函数
- eoe android客户端源码剖析(一)动画启动界面
- 丰富干货:CocoaChina上海沙龙全程揭秘
- [后缀数组+二分] poj 3294 Life Forms
- piwik -开启cron处理报表
- 骨牌铺方格
- mfs源码分析,学习笔记