HDU 4069 Squiggly Sudoku 【DLX+BFS】

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4069
在这里插入图片描述
在这里插入图片描述
★这题一开始题都看不懂,后来发现还是挺有意思的


题意:

给你一个9x9的矩阵, 矩阵里面有一些墙将数字划分为9个包含9个数字的宫 ,现在要问你能不能找到一种填数字的办法,使得矩阵的 每一行 每一列 每一宫 都包含9个不同的数字
而输入告诉你每个点的哪个方向有墙,输入中的81个数代表的意思是这样的:
如果这个数所在的单元没有墙,那这个数就是它本身,否则左边有墙就加128,下面有加64,右边有加32,上面有加16 比如第一个数144=128+16 故它所在的地方上面和左边有墙,而第二个数18=16+2即上面有墙值为2


思路:

玩过一般的数独,就是给一个9x9的矩阵,你要往里面填数字,必须满足哪些行、列包含1至9的所有数字。
但这题加了点难度,我写的上一题是划分为9个小3*3的方阵,这题是9个形状变化的宫
但其实也还好,我们只要先找到那些单元在哪些宫就好了。这里通过BFS解决,DFS好像也可以吧

BFS

广搜前先记录下哪些单元的哪些方向有墙,有墙当然不走那个方向。然后就基本上是普通的BFS了。

void bfs(int x,int y,int c) //x y即坐标 c就是所在的宫id   从1到9
{
    queue<point> q;
    vis[x][y]=1;
    p[x][y].plc=c;        
    point now=p[x][y];
    q.push(now);
    while(q.size()){
        now=q.front();
        q.pop();              
        for(int i=0;i<4;i++){   //四个方向
            if(!now.d[i]){      //没墙可走
                int xx=now.x+D[i][0];   
                int yy=now.y+D[i][1];
                if(!vis[xx][yy]){       //没被标记过 
                    vis[xx][yy]=1;
                    p[xx][yy].plc=c;
                    q.push(p[xx][yy]);
                }
            }
        }
    }
}
DLX

然后剩下的基本是DLX求数独的老套路了,以每个点放什么数为行 最多81x9行 ,以每个点放了没(1-81)、每一行放了什么数(82-162)、每一列放了什么数(163-243)、每一宫放了什么数(244-324)为列
就是在dance的时候稍稍修改,判断如果有两个答案就直接return ;


代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<stack>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
using namespace std;
const int N=81*9*81*4+5;
const int M=81*9+5;
const int inf=0x7fffffff;
const int mod=1e9+7;
const double eps=1e-8;
const double pi=acos(-1);
typedef long long LL;
template<class T>
void read(T &x)
{
    char c; x=1;
    while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
    T res=c-'0';
    while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
    x*=res;
}
int D[4][2]={{0,-1},{1,0},{0,1},{-1,0}}; //left down right up
struct DLX
{
    int n,m,cnt,num;
    int up[N],right[N],left[N],down[N];
    int col[N],head[M],sz[M];
    int test[N],get[N][3],ans[N];
    void init(int nn,int mm)
    {
        n=nn; m=mm;
        num=0;
        for(int i=0;i<=m;i++){
            up[i]=down[i]=i;
            left[i]=i-1;
            right[i]=i+1;
            sz[i]=0;
        }
        cnt=m;
        left[0]=m; right[m]=0;
        for(int i=1;i<=n;i++) head[i]=-1;
    }
    void link(int r,int c,int x,int y,int v)
    {
        cnt++;
        col[cnt]=c;
        sz[c]++;
        up[cnt]=up[c];
        down[cnt]=c;
        down[up[c]]=cnt;
        up[c]=cnt;
        get[cnt][0]=x; get[cnt][1]=y; get[cnt][2]=v;
        if(head[r]==-1) head[r]=left[cnt]=right[cnt]=cnt;
        else{
            int tmp=head[r];
            right[cnt]=tmp;
            left[cnt]=left[tmp];
            right[left[tmp]]=cnt;
            left[tmp]=cnt;
        }
    }
    void Remove(int c)
    {
        right[left[c]]=right[c];
        left[right[c]]=left[c];
        for(int i=down[c];i!=c;i=down[i]){
            for(int j=right[i];j!=i;j=right[j]){
                up[down[j]]=up[j];
                down[up[j]]=down[j];
                sz[col[j]]--;
            }
        }
    }
    void Resume(int c)
    {
        right[left[c]]=left[right[c]]=c;
        for(int i=up[c];i!=c;i=up[i]){
            for(int j=right[i];j!=i;j=right[j]){
                up[down[j]]=down[up[j]]=j;
                sz[col[j]]++;
            }
        }
    }
    void dance(int dep)
    {
//        cout<<dep<<endl;
        if(right[0]==0&&dep==81){
            num++;
            for(int i=0;i<81;i++) ans[i]=test[i];
            return ;
        }
        if(right[0]==0||num>=2) return ;
        int now=right[0];
        for(int i=now;i!=0;i=right[i]){
            if(sz[i]<sz[now]) now=i;
        }
        Remove(now);
        for(int i=down[now];i!=now;i=down[i]){
            test[dep]=i;
            for(int j=right[i];j!=i;j=right[j]) Remove(col[j]);
            dance(dep+1);
            if(num>=2) return ;
            for(int j=left[i];j!=i;j=left[j]) Resume(col[j]);
        }
        Resume(now);
    }
}dlx;
struct point
{
    int x,y,plc,val;   //(x,y),place,value
    int d[4];      //direction
}p[10][10];
bool vis[10][10];
void bfs(int x,int y,int c)
{
    queue<point> q;
    vis[x][y]=1;
    p[x][y].plc=c;
    point now=p[x][y];
    q.push(now);
    while(q.size()){
        now=q.front();
        q.pop();
        for(int i=0;i<4;i++){
            if(!now.d[i]){
                int xx=now.x+D[i][0];
                int yy=now.y+D[i][1];
                if(!vis[xx][yy]){
                    vis[xx][yy]=1;
                    p[xx][yy].plc=c;
                    q.push(p[xx][yy]);
                }
            }
        }
    }
}
void hhh(int x,int y,int v,int &s)
{
    s++;
    int p1=(x-1)*9+y;    //(x,y) 放过了
    int p2=(x-1)*9+v+81;    //x行放了数字v
    int p3=(y-1)*9+v+81*2;   //y列放了数字v
    int p4=(p[x][y].plc-1)*9+v+81*3;  //宫plc放过了数字v
    dlx.link(s,p1,x,y,v);
    dlx.link(s,p2,x,y,v);
    dlx.link(s,p3,x,y,v);
    dlx.link(s,p4,x,y,v);
}
int main()
{
    int t;
    read(t);
    int cas=0;
    while(t--){
        memset(p,0,sizeof p);
        for(int i=1;i<=9;i++){
            for(int j=1;j<=9;j++){
                read(p[i][j].val);
                p[i][j].x=i; p[i][j].y=j;
                if(p[i][j].val>=128){ //there is a wall on left
                    p[i][j].val-=128;
                    p[i][j].d[0]=1;
                }
                if(p[i][j].val>=64){ //there is a wall on down
                    p[i][j].val-=64;
                    p[i][j].d[1]=1;
                }
                if(p[i][j].val>=32){ //there is a wall on right
                    p[i][j].val-=32;
                    p[i][j].d[2]=1;
                }
                if(p[i][j].val>=16){ //there is a wall on up
                    p[i][j].val-=16;
                    p[i][j].d[3]=1;
                }
            }
        }
        int cnt=0;
        memset(vis,0,sizeof vis);
        for(int i=1;i<=9;i++){
            for(int j=1;j<=9;j++){
                if(!vis[i][j]){
                    bfs(i,j,++cnt);
                }
            }
        }
        cnt=0;
        int pp=0;
        dlx.init(81*9,81*4);
        for(int i=1;i<=9;i++){
            for(int j=1;j<=9;j++){
                if(p[i][j].val==0){
                    pp++;
                    for(int k=1;k<=9;k++)
                        hhh(i,j,k,cnt);
                }
                else hhh(i,j,p[i][j].val,cnt);

            }
        }
        dlx.dance(0);
        printf("Case %d:\n",++cas);
        if(dlx.num==0) cout<<"No solution\n";
        else if(dlx.num==2) cout<<"Multiple Solutions\n";
        else{
            int res[10][10];
            for(int i=0;i<81;i++){
                int t=dlx.ans[i];
                int x=dlx.get[t][0];
                int y=dlx.get[t][1];
                int v=dlx.get[t][2];
                res[x][y]=v;
            }
            for(int i=1;i<=9;i++){
                for(int j=1;j<=9;j++){
                    cout<<res[i][j];
                }
                cout<<endl;
            }
        }
    }
    return 0;
}
发布了71 篇原创文章 · 获赞 89 · 访问量 8539

猜你喜欢

转载自blog.csdn.net/weixin_43890662/article/details/102883523
今日推荐