建模思路跟之前的一样,宫的话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; }
原文地址:https://www.cnblogs.com/ZhenghangHu/p/9745958.html
时间: 2024-11-08 03:42:33