• POJ 3076 Sudoku (dancing links)


    题目大意:

    16*16的数独。


    思路分析:

    多说无益.

    想说的就是dancing links 的行是依照

    第一行第一列填 1

    第一行第二列填 2

    ……

    第一行第十五列填15

    第一行第二列填 1

    ……

    第二行。。。。



    列的纺织则是

    第一行放1,第一行放2,。。第十六行放16.。。第一列放1.。第一列放2.。。第十六列放16.。第一块区域放1 。。。。然后在最后81位就是放自己的位置,准确的说就是 r*m+c。


    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #define maxn 16*16*16*16*16*4+5
    #define inf 0x3f3f3f3f
    using namespace std;
    
    int n=16*16*9,m=16*16*4,p;
    int map[16*16*16+5][16*16*4+5];
    int L[maxn],R[maxn],D[maxn],U[maxn],S[maxn],O[maxn],col[maxn],row[maxn],head,cnt;
    int num;
    
    void dancing_links_init()
    {
        head=0;
        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++)
        {
            int rowh=-1;
            for(int j=1;j<=m;j++)
            {
                if(map[i][j])
                {
                    S[j]++;
                    U[cnt]=U[j];
                    D[U[j]]=cnt;
                    U[j]=cnt;
                    D[cnt]=j;
                    row[cnt]=i;
                    col[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 Remove(const int &c)
    {
        L[R[c]]=L[c];
        R[L[c]]=R[c];
        for(int i=D[c];i!=c;i=D[i])
        {
            for(int j=R[i];j!=i;j=R[j])
            {
                U[D[j]]=U[j];
                D[U[j]]=D[j];
                --S[col[j]];
            }
        }
    }
    void Resume(const int &c)
    {
        for(int i=U[c];i!=c;i=U[i])
        {
            for(int j=L[i];j!=i;j=L[j])
            {
                ++S[col[j]];
                U[D[j]]=j;
                D[U[j]]=j;
            }
        }
        L[R[c]]=c;
        R[L[c]]=c;
    }
    bool dfs(const int &k)//可行解
    {
        if(head==R[head])
        {
            sort(O,O+256);
            for(int i=0;i<256;i++)
            {
                printf("%c",O[i]-i*16+'A'-1);
                if(i%16==15)puts("");
            }
            puts("");
            return true;
        }
        int mx=inf,cur=0;
        for(int t=R[head];t!=head;t=R[t])
        {
            if(S[t]<mx)
            {
                mx=S[t];
                cur=t;
            }
        }
        Remove(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])
            {
                Remove(col[j]);
            }
            if(dfs(k+1))return true;
            for(int j=L[i];j!=i;j=L[j])
            {
                Resume(col[j]);
            }
        }
        Resume(cur);
        return false;
    }
    /*
    void dfs(const int &k)//最优解
    {
        if(R[head]==head)
        {
            if(k<num)num=k;
            return;
        }
        if(k>=num)return;
        int mx=inf,cur=0;
        for(int t=R[head];t!=head;t=R[t])
        {
            if(S[t]<mx)
            {
                mx=S[t];
                cur=t;
            }
        }
        Remove(cur);
        for(int i=D[cur];i!=cur;i=D[i])
        {
            for(int j=R[i];j!=i;j=R[j])
            {
                Remove(col[j]);
            }
            dfs(k+1);
            for(int j=L[i];j!=i;j=L[j])
            {
                Resume(col[j]);
            }
        }
        Resume(cur);
    }
    */
    char tmp[16][1111];
    char str[1111];
    int main()
    {
        while(scanf("%s",tmp[0])!=EOF)
        {
            for(int i=1;i<16;i++)scanf("%s",tmp[i]);
            int cnt=0;
            for(int i=0;i<16;i++)
            for(int j=0;j<16;j++)
            str[cnt++]=tmp[i][j];
    
            memset(map,0,sizeof map);
            int len=cnt;
            for(int i=0;i<len;i++)
            {
                int r=i/16;
                int c=i-r*16;
                int base=(r*16+c)*16;
    
                if(str[i]=='-')
                {
                    for(int k=1;k<=16;k++)
                    {
                        map[base+k][r*16+k]=1;
                        map[base+k][256+c*16+k]=1;
                        map[base+k][256+256+16*(4*(r/4)+(c/4))+k]=1;
                        map[base+k][256*3+r*16+c+1]=1;
                    }
                }
                else
                {
                    int k=str[i]-'A'+1;
                    map[base+k][r*16+k]=1;
                    map[base+k][256+c*16+k]=1;
                    map[base+k][256+256+16*(4*(r/4)+(c/4))+k]=1;
                    map[base+k][256+256+256+r*16+c+1]=1;
                }
            }
            dancing_links_init();
            dfs(0);
        }
        return 0;
    }
    


  • 相关阅读:
    Android 关于ExpandableListView控件setOnChildClickListener无效问题
    Android SnapHelper
    Android java判断字符串包含某个字符段(或替换)
    Android中的CharSequence和String
    Java时间和时间戳的相互转换
    比较运算符和函数(四十一)
    数值运算符和函数(四十)
    字符函数(三十九)
    多表删除(三十八)
    无限级分类表设计(三十七)
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/3930862.html
Copyright © 2020-2023  润新知