HDU 4069 Squiggly Sudoku舞蹈链样例坑

Posted zhenghanghu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 4069 Squiggly Sudoku舞蹈链样例坑相关的知识,希望对你有一定的参考价值。

建模思路跟之前的一样,宫的话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舞蹈链样例坑的主要内容,如果未能解决你的问题,请参考以下文章

hdu 4069 垃圾数独

HDU 1426 Sudoku Killer(dfs 解数独)

HDU 1426 Sudoku KillerDFS 数独

hdu第4场j.Let Sudoku Rotate

hdu6341 Problem J. Let Sudoku Rotate (dfs)

HDU-6341 Problem J. Let Sudoku Rotate(dfs 剪枝)