1. 程式人生 > >HDU 4069 Squiggly Sudoku【舞蹈鏈】【樣例坑】

HDU 4069 Squiggly Sudoku【舞蹈鏈】【樣例坑】

space ios names sudoku clas class pac multipl 就是

建模思路跟之前的一樣,宮的話dfs搜索一下找聯通分量就行,好像也沒有更好的辦法,有的話請評論哈orz

——因為舞蹈鏈一般找到解以後就直接跳出了,所以ans數組就是ans不會再變。但這題讓找一下有沒有多組解,所以就不能找到一個解後直接跳出。就有一個小坑是都搜完後ans數組可能不是合法ans,所以找到第一個解的時候要單獨存一下才能ac

——但這個樣例就是如果中間不存一下ans數組的話,樣例還是能過。。。

——那應該就是正好最後一次枚舉的時候找到了這個解??

——不然的話它回溯的時候枚舉下一個可能會覆蓋原來ans數組的

#include<iostream>
#include<cstdio>
#include
<cstring> #include<cmath> #include<queue> #include<map> #include<iomanip> #include<algorithm> #include<vector> #define INF 2e9 #define maxnode 100000 using namespace std; int dx[4]={0,0,1,-1}; int dy[4]={1,-1,0,0}; int board[10][10],vis[100],an[100]; vector<int> edge[100
]; int cnt; void dfs(int u){ vis[u]=cnt; for(int i=0;i<edge[u].size();i++){ int v=edge[u][i]; if( !vis[v] ) dfs(v); } } struct DLX{ int up[maxnode],down[maxnode],L[maxnode],R[maxnode]; int row[maxnode],col[maxnode],h[5000],s[350]; int n,m,size,ansd,ans[5000];
void init(int n1,int m1){ n=n1; m=m1; for(int i=0;i<=m;i++){ up[i]=down[i]=i; L[i]=i-1; R[i]=i+1; s[i]=0; } L[0]=m; R[m]=0; ansd=0; size=m; for(int i=1;i<=n;i++) h[i]=-1; } void link(int r,int c){ row[++size]=r; col[size]=c; s[c]++; up[size]=up[c]; down[size]=c; down[up[c]]=size; up[c]=size; if( h[r]==-1 ) h[r] = L[size] = R[size] = size; else{ L[size]=L[h[r]]; R[size]=h[r]; R[L[h[r]]]=size; L[h[r]]=size; } } void remove(int c){ L[R[c]]=L[c]; R[L[c]]=R[c]; for(int i=down[c];i!=c;i=down[i]){ for(int j=R[i];j!=i;j=R[j]){ up[down[j]]=up[j]; down[up[j]]=down[j]; s[ col[j] ]--;//忘寫這一行的話會慢很多但不會錯 } } } void resume(int c){ L[R[c]]=c; R[L[c]]=c; for(int i=down[c];i!=c;i=down[i]){ for(int j=R[i];j!=i;j=R[j]){ up[down[j]]=j; down[up[j]]=j; s[ col[j] ]++; } } } bool dance(int d){ // cout<<d<<" "<<R[0]<<endl; if( R[0]==0 ){ if( ansd!=0 ) return true; ansd=d; for(int i=0;i<81;i++) an[i]=ans[i]; return false;//目前還沒有搜到multiple solution } int c=R[0]; for(int i=c;i!=0;i=R[i]) if( s[i]<s[c] ) c=i; remove(c); for(int i=down[c];i!=c;i=down[i]){ ans[d]=row[i]; for(int j=R[i];j!=i;j=R[j]) remove( col[j] ); if( dance(d+1) ) return true; for(int j=L[i];j!=i;j=L[j]) resume( col[j] ); } resume(c); return false; } }dlx; struct node{ int r,c,num; node(int r1=0,int c1=0,int n1=0): r(r1),c(c1),num(n1) {} }biao[5000]; int main(){ ios::sync_with_stdio(false); int t; cin>>t; int cas=0; while(t--){ memset(vis,0,sizeof(vis)); for(int i=0;i<100;i++) edge[i].clear(); cnt=0; for(int i=0;i<9;i++){ for(int j=0;j<9;j++){ int id=i*9+j+1; cin>>board[i][j]; if( board[i][j]>=128 ) board[i][j]-=128;//左邊 else edge[id].push_back( id-1 ); if( board[i][j]>=64 ) board[i][j]-=64; else edge[id].push_back( id+9 );//down if( board[i][j]>=32 ) board[i][j]-=32;//right else edge[id].push_back( id+1 ); if( board[i][j]>=16 ) board[i][j]-=16;//up else edge[id].push_back( id-9 ); } } for(int i=1;i<=81;i++){ if( !vis[i] ){ cnt++; dfs(i); } } //這樣一來就都分好了宮 dlx.init(4000,324); int rows=0; for(int i=0;i<9;i++){ for(int j=0;j<9;j++){ int id=i*9+j+1; if( board[i][j]==0 ){ for(int k=1;k<=9;k++){ rows++; dlx.link(rows,id); dlx.link(rows,81+i*9+k);// dlx.link(rows,162+j*9+k);// dlx.link(rows,243+(vis[id]-1)*9+k); biao[rows]=node(i,j,k); // cout<<rows<<" "<<id<<" "<<81+i*9+k <<" "<<162+j*9+k <<" "<<243+(vis[id]-1)*9+k<<endl; } } else{ rows++; dlx.link(rows,id); dlx.link(rows,81+i*9+board[i][j]); dlx.link(rows,162+j*9+board[i][j]); dlx.link(rows,243+(vis[id]-1)*9+board[i][j]); biao[rows]=node(i,j,board[i][j]); // cout<<rows<<" "<<id<<" "<<81+i*9+board[i][j] <<" "<<162+j*9+board[i][j] <<" "<<243+(vis[id]-1)*9+board[i][j]<<endl; } } } cout<<"Case "<<++cas<<":"<<endl; if( dlx.dance(0) ) cout<<"Multiple Solutions"<<endl; else if(dlx.ansd){ for(int i=0;i<=80;i++){ node p=biao[ an[i] ]; board[p.r][p.c]=p.num; } for(int i=0;i<9;i++){ for(int j=0;j<9;j++) cout<<board[i][j]; cout<<endl; } } else cout<<"No solution"<<endl; } return 0; }

HDU 4069 Squiggly Sudoku【舞蹈鏈】【樣例坑】