hdu 4069 Squiggly Sudoku——11年福州网络赛DLX

5 篇文章 0 订阅
1 篇文章 0 订阅

建图转成0/1矩阵。

就是先dfs把一个区域的块标号一下。

然后十字链表搞DLX...其实方法暴力了。据说直接建链表就行。我们这方法用C++会TLE,G++能过。感谢HDU超强服务器。


PS:这题我们卡了一个地方,就是找到解的时候必须马上记录,如下面代码的oo数组。不能最后再输出,因为找到解后还会继续回溯的,会破坏o数组。可惜样例看不出来……卡了好久才过的。

#include <algorithm>
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <stack>
#include <fstream>
#include <numeric>
#include <iomanip>
#include <bitset>
#include <list>
#include <stdexcept>
#include <functional>
#include <utility>
#include <ctime>
using namespace std;

int head=0;
const int INF=10000000;
const int MAX=750*350;

int dir[4]= {16, 32, 64, 128};
int tt[4][2]=
{
    {-1, 0},
    {0, 1},
    {1, 0},
    {0, -1}
};

struct node
{
    int oo[100];
    int mat[750][350], tor[750], toc[750], dig[750];
    int n, m, o[1010], c[MAX], s[MAX], u[MAX], d[MAX], l[MAX], r[MAX], row[MAX];
    int cnt, rowh;
    int g[15][15];
    int id[15][15];
    int Num[15][15];
    int hl;
    int res;
    void makegragh()
    {
        int nn, i, j, k, row, col, qua, pos, num;
        memset(mat, 0, sizeof(mat));
        n=1;
        m=324;
        cnt=0;
        for(i=1; i<=9; i++)
        {
            for(j=1; j<=9; j++)
            {
                row=i;
                col=j;
                qua=id[i][j]+1;
                pos=(i-1)*9+j;
                if(Num[i][j]==0)
                {
                    for(k=1; k<=9; k++)
                    {
                        tor[n]=i;
                        toc[n]=j;
                        dig[n]=k;
                        mat[n][(row-1)*9+k]=1;
                        mat[n][81+(col-1)*9+k]=1;
                        mat[n][162+(qua-1)*9+k]=1;
                        mat[n++][243+pos]=1;
                    }
                }
                else
                {
                    tor[n]=i;
                    toc[n]=j;
                    num=Num[i][j];
                    dig[n]=num;
                    mat[n][(row-1)*9+num]=1;
                    mat[n][81+(col-1)*9+num]=1;
                    mat[n][162+(qua-1)*9+num]=1;
                    mat[n++][243+pos]=1;
                }
                cnt++;
            }
        }
        n--;
    }
    void myremove(const int &cur)
    {
        l[r[cur]]=l[cur];
        r[l[cur]]=r[cur];
        for(int i=d[cur]; i!=cur; i=d[i])
        {
            for(int j=r[i]; j!=i; j=r[j])
            {
                u[d[j]]=u[j];
                d[u[j]]=d[j];
                --s[c[j]];
            }
        }
    }
    void myresume(const int &cur)
    {
        for(int i=u[cur]; i!=cur; i=u[i])
        {
            for(int j=l[i]; j!=i; j=l[j])
            {
                ++s[c[j]];
                u[d[j]]=j;
                d[u[j]]=j;
            }
        }
        l[r[cur]]=cur;
        r[l[cur]]=cur;
    }
    void dfs(const int &k)
    {
        if(res>1)
            return ;
//        if (k>81) return;
        if (r[head]==head)
        {
            res++;
            if (res==1)
            {
                for (int i=0; i<81; i++) oo[i]=o[i];
                sort(oo, oo+81);
            }
            return ;
        }
        int ms=INF, cur=0;
        for(int t=r[head]; t!=head; t=r[t])
        {
            if(s[t]<ms)
            {
                ms=s[t];
                cur=t;
            }
        }
        myremove(cur);
        for(int i=d[cur]; i!=cur; i=d[i])
        {
            o[k]=row[i];
            for(int j=r[i]; j!=i; j=r[j])
                myremove(c[j]);
            dfs(k+1);
            if(res>1)
                return ;
            for(int j=l[i]; j!=i; j=l[j])
                myresume(c[j]);
        }
        if(res>1)
            return ;
        myresume(cur);
        return ;
    }
    void dfs1(int x, int y, int hh)
    {
        id[x][y]=hh;
        for(int i=0; i<4; i++)
        {
            if(dir[i]&g[x][y])
                continue;
            int x1=x+tt[i][0];
            int y1=y+tt[i][1];
            if((x1<1)||(y1<1)||(x1>9)||(y1>9))
                continue;
            if(id[x1][y1]!=-1)
                continue;
            dfs1(x1, y1, hh);
        }
    }
    void init()
    {
        res=hl=0;
        memset(id, -1, sizeof(id));
        for(int i=1; i<=9; i++)
        {
            for(int j=1; j<=9; j++)
            {
                scanf("%d", &g[i][j]);
                Num[i][j]=g[i][j];
                for(int k=3; k>=0; k--)
                {
                    if(Num[i][j]>=dir[k])
                        Num[i][j]-=dir[k];
                }
//				g[i][j]-=Num[i][j];
            }
        }
        for(int i=1; i<=9; i++)
        {
            for(int j=1; j<=9; j++)
                if(id[i][j]==-1)
                {
                    dfs1(i, j, hl++);
                }
        }
        head=0;
        makegragh();
        memset(s, 0, sizeof(s));

        for(int i=head; i<=m; i++)
        {
            r[i]=(i+1)%(m+1);
            l[i]=(i-1+m+1)%(m+1);
            u[i]=d[i]=i;
        }
        cnt=m+1;
        for(int i=1; i<=n; i++)
        {
            rowh=-1;
            for(int j=1; j<=m; j++)
                if(mat[i][j])
                {
                    s[j]++;
                    u[cnt]=u[j];
                    d[u[j]]=cnt;
                    u[j]=cnt;
                    d[cnt]=j;
                    row[cnt]=i;
                    c[cnt]=j;
                    if(rowh==-1)
                    {
                        l[cnt]=r[cnt]=cnt;
                        rowh=cnt;
                    }
                    else
                    {
                        l[cnt]=l[rowh];
                        r[l[rowh]]=cnt;
                        r[cnt]=rowh;
                        l[rowh]=cnt;
                    }
                    cnt++;
                }
        }
    }
    void print()
    {
        if(res==0)
            printf("No solution\n");
        else if(res>1)
        {
            printf("Multiple Solutions\n");
        }
        else
        {
//            sort(o, o+81);
            for(int i=0; i<9; i++)
            {
                for(int j=0; j<9; j++)
                {
                    printf("%d", dig[oo[i*9+j]]);
                }
                printf("\n");
            }
        }
    }
} dlx;

int Case;

void solve()
{
    Case++;
    dlx.init();
    printf("Case %d:\n", Case);
    dlx.dfs(0);
    dlx.print();
}

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
        solve();
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值