[DLX]HDOJ4069 Squiggly Sudoku
2015-09-18 22:21
435 查看
题意:有9*9的格子
每个格子 由五部分组成:上(16)、右(32)、下(64)、左(128)、和该格的数值(0~9)
若上下左右有分割格子的线 就加上相应的数, 该格的数值若为0,则是未知 1~9 则是已知
然后根据分割线 做数独(每行、每列、每宫都是1~9)
输出无解、多解或者一个解就输出那个解
这种数独与普通3*3的数独 的唯一区别就是 宫 的划分的方式不一样
16、32、64、128这几个数很特殊 分别是$2^4$、$2^5$、$2^6$、$2^7$
也就是相应的二位数,若第4位为1,则上面有分割线
若第5位为1,则右边有分割线
若第6位为1,则下面有分割线
若第7位为1,则左边有分割线
那么只要随便dfs一下确定在哪个宫里就好啦
然后把模板里 本来宫的位置是(i/3)*3+(j/3) 换成 dfs搜出来的宫的位置就好啦~
HDOJ 4069
每个格子 由五部分组成:上(16)、右(32)、下(64)、左(128)、和该格的数值(0~9)
若上下左右有分割格子的线 就加上相应的数, 该格的数值若为0,则是未知 1~9 则是已知
然后根据分割线 做数独(每行、每列、每宫都是1~9)
输出无解、多解或者一个解就输出那个解
这种数独与普通3*3的数独 的唯一区别就是 宫 的划分的方式不一样
16、32、64、128这几个数很特殊 分别是$2^4$、$2^5$、$2^6$、$2^7$
也就是相应的二位数,若第4位为1,则上面有分割线
若第5位为1,则右边有分割线
若第6位为1,则下面有分割线
若第7位为1,则左边有分割线
那么只要随便dfs一下确定在哪个宫里就好啦
然后把模板里 本来宫的位置是(i/3)*3+(j/3) 换成 dfs搜出来的宫的位置就好啦~
#include <bits/stdc++.h> using namespace std; typedef long long LL; //const int N=2e5+5; const int N=9; //3*3数独 const int MaxN=N*N*N+10; // 一格能填9个数 9*9格 const int MaxM=N*N*4+10; // 9*9*4=(9+9+9)*9+9*9 (9+9+9)是9行 9列 9格 *9是9个数 9*9是81个格子 const int maxnode=MaxN*4+MaxM+10; int g[MaxN]; int anss; struct DLX { int n, m, size; int U[maxnode], D[maxnode], R[maxnode], L[maxnode], Row[maxnode], Col[maxnode]; int H[MaxN], S[MaxM]; // S: 各列节点数 int ansd, ans[MaxN]; void init(int _n, int _m) { n=_n; m=_m; for(int i=0; i<=m; i++) { S[i]=0; //每一列元素个数 U[i]=D[i]=i;//上下指针 L[i]=i-1; //← R[i]=i+1; //→ } R[m]=0; //循环 最后一个指向第一个 L[0]=m; //第一个往前指向最后一个 size=m; // 节点总数 for(int i=1; i<=n; i++) H[i]=-1; //头指针 } void Link(int r, int c) { S[Col[++size]=c]++; Row[size]=r; D[size]=D[c]; U[D[c]]=size; U[size]=c; D[c]=size; if(H[r]<0) H[r]=L[size]=R[size]=size; else { R[size]=R[H[r]]; L[R[H[r]]]=size; L[size]=H[r]; R[H[r]]=size; } } 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[Col[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[Col[U[D[j]]=D[U[j]]=j]]++; L[R[c]]=R[L[c]]=c; } void Dance(int d) { if(anss>1) return ; if(R[0]==0) { for(int i=0;i<d;i++) g[(ans[i]-1)/N]=(ans[i]-1)%N+1; anss++; } int c=R[0]; for(int i=R[0]; i!=0; i=R[i]) if(S[i]<S[c]) c=i; remove(c); for(int i=D[c]; i!=c; i=D[i]) { ans[d]=Row[i]; for(int j=R[i]; j!=i; j=R[j]) remove(Col[j]); Dance(d+1); for(int j=L[i]; j!=i; j=L[j]) resume(Col[j]); } resume(c); } } dlx; int s[10][10]; int vis[10][10]; void dfs(int x,int y,int col) { if(x<0||x>=9||y<0||y>=9||vis[x][y]!=-1) return ; if((s[x][y]&(1<<7))==0) { vis[x][y]=col; dfs(x,y-1, col); } if((s[x][y]&(1<<6))==0) { vis[x][y]=col; dfs(x+1,y, col); } if((s[x][y]&(1<<5))==0) { vis[x][y]=col; dfs(x,y+1, col); } if((s[x][y]&(1<<4))==0) { vis[x][y]=col; dfs(x-1,y, col); } } void palce(int &r, int &c1, int &c2, int &c3, int &c4, int i, int j, int k) { r=(i*N+j)*N+k; // 第几行 c1=i*N+j+1; // 第几个格子 c2=N*N+i*N+k; // 第i行上的k c3=N*N*2+j*N+k; // 第j列上的k c4=N*N*3+(vis[i][j])*N+k; // 某宫中的k; } int main() { int t, ca=1; scanf("%d", &t); while(t--) { for(int i=0;i<N;i++) for(int j=0;j<N;j++) scanf("%d", &s[i][j]); int num=0; memset(vis, -1, sizeof(vis)); for(int i=0;i<N;i++) for(int j=0;j<N;j++) { if(vis[i][j]==-1) dfs(i, j, num++); if((s[i][j]-(1<<7))>=0) s[i][j]-=1<<7; if((s[i][j]-(1<<6))>=0) s[i][j]-=1<<6; if((s[i][j]-(1<<5))>=0) s[i][j]-=1<<5; if((s[i][j]-(1<<4))>=0) s[i][j]-=1<<4; } dlx.init(N*N*N, 4*N*N); for(int i=0; i<N; i++) for(int j=0; j<N; j++) for(int k=1; k<=9; k++) if(s[i][j]==0 || s[i][j]==k) { int r, c1, c2, c3, c4; palce(r, c1, c2, c3, c4, i, j, k); dlx.Link(r, c1); dlx.Link(r, c2); dlx.Link(r, c3); dlx.Link(r, c4); } anss=0; dlx.Dance(0); printf("Case %d:\n", ca++); if(anss==0) puts("No solution"); else if(anss>1) puts("Multiple Solutions"); else { for(int i=0;i<N;i++) { for(int j=0;j<N;j++) printf("%d", g[i*N+j]); puts(""); } } } return 0; }
HDOJ 4069
相关文章推荐
- 交互设计必懂--开发有价值的用户体验
- 增加用户体验的细节--三个按钮的交互设计思维
- 零基础掌握交互设计的重点笔记
- UI_UISegmentedControl
- Webserver issues | PHP manager for IIS
- UI_UISlider
- iOS开发笔记--UILabel的相关属性设置
- UI_UIStepper
- UI控件以及视图控制器执行时的几种常使用到的方法
- UI控件Lable和Button的简单总结
- 滚动视图(UIScrollView)
- UI12_AVAudioPlayer
- Android笔记(三十三) Android中线程之间的通信(五)Thread、Handle、Looper和MessageQueue
- UITableView(表视图)使用详解
- UI11_手势
- 使用UIImageView实现动画
- General Problem Solving Techniques [Examples]~A
- HDU 4027 Can you answer these queries (有意思的线段树)
- General Problem Solving Techniques [Beginner-1]~B
- UI-滚动视图(滚动视图)