数独数独(DFS +状態の圧縮)

Sudoku数独

トピックアドレスします。https://ac.nowcoder.com/acm/problem/51013

問題の意味

プログラミング9x9の数独

エントリー

81文字の文字列として9×9つの入力の数は、「」充填の所望の数を表します。
ターミネータとして「終了」で

輸出

入力の異なる形式、81桁の数字。
ここに画像を挿入説明

問題の解決策

状態削減:数独の必要性は、各行、各列に、互いに異なる各家屋番号は、それのようなバイナリ形式で、この3例、言うことができることを確実にするため
、昇降数独の一部、最初の行最初の列、最初の家:
?71?4958
?35
?8 4

。9

1

。6
。8

最初の行は、000100110のように表される:この数は、すなわちフラグが0である場合、何のフラグ、すなわちストレージの便宜、小数への保存、38、1ではない
000010010のように表される最初の列の
最初の家が100100010として発現します

そうのみこれらの3例、「および」動作が得られる小数点数、両方の位置1のために、得られ、そして順次取得lowbitによって得られた、それぞれの数を表すことができ、すべてのNULL値を記録することのみが必要ですあなたはビット操作ですべてのNULL値のDFSへの最後の答えを得ることができます。
データは、ソリューションを確実にするためなので、のみ、最後に戻ってあまりにも多くの時間を避けるために、埋めるヌルの少ない可能性を取るため、復帰に埋めるための条件を、満たすことができる数独ソリューションを満たすために出力する必要があります、あまりにもこの質問に追加するには、この最適化の必要性。

コード

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 12
#define maxm 100
#define INF 2147483640
#define IOS ios::sync_with_stdio(false)
#define mod 10007

struct node{
    int x,y;
};

int ff[N][N];
int R[N],C[N],G[N/3][N/3]; //状态压缩,1表示空值
vector<node>V;  //记录所有空值的坐标

int mp[1<<N],ones[1<<N];

int lowbit(int i)   //返回低位1
{
    return i&(-i);
}

int get_num(int x,int y)   //得到当前坐标,可以放那些数,返回状态压缩的值
{
    return R[x]&C[y]&G[x/3][y/3];
}

int get_one(int x)
{
    int cnt=0;
    while(x)
    {
        if(x%2==1)
            cnt++;
        x=x>>1;
    }
    return cnt;
}

bool dfs(int cur)
{
    if(cur==V.size())
        return true;

    int minv=12,id=0;
    for(int i=0;i<V.size();i++)
        if(ff[V[i].x][V[i].y]==0)
        {
            int t=ones[get_num(V[i].x,V[i].y)];
            if(t<minv)
            {
                minv=t;
                id=i;
            }
        }

    node tt=V[id];
    for(int i=get_num(tt.x,tt.y);i;i-=lowbit(i))
    {
        int va=lowbit(i);
        ff[tt.x][tt.y]=mp[va];
        R[tt.x]-=va;
        C[tt.y]-=va;
        G[tt.x/3][tt.y/3]-=va;
        if(dfs(cur+1))
            return true;
        R[tt.x]+=va;
        C[tt.y]+=va;
        G[tt.x/3][tt.y/3]+=va;
        ff[tt.x][tt.y]=0;
    }
    return false;
}

void init()
{
    V.clear();
    for(int i=0;i<N;i++)
    {
        R[i]=(1<<9)-1;
        C[i]=(1<<9)-1;
    }
    for(int i=0;i<N/3;i++)
        for(int j=0;j<N/3;j++)
            G[i][j]=(1<<9)-1;
}

int main()
{
    IOS;
    for(int i=0;i<9;i++)
        mp[1<<i]=i+1;
    for(int i=0;i<(1<<N);i++)
        ones[i]=get_one(i);

    string str;
    while(true)
    {
        cin>>str;
        if(str[0]=='e')
            break;

        init();
        for(int i=0; i<9; i++)
            for(int j=0; j<9; j++)
            {
                if(str[i*9+j]=='.')
                {
                    ff[i][j]=0;
                    V.push_back(node{i,j});
                }
                else
                {
                    ff[i][j]=str[i*9+j]-48;
                    int t=ff[i][j];
                    R[i]-=(1<<t-1);
                    C[j]-=(1<<t-1);
                    G[i/3][j/3]-=(1<<t-1);
                }
            }

        dfs(0);
        string ans="";
        for(int i=0; i<9; i++)
            for(int j=0; j<9; j++)
                ans.push_back(ff[i][j]+48);
        cout<<ans<<"\n";
    }
    return 0;
}

公開された44元の記事 ウォンの賞賛4 ビュー2211

おすすめ

転載: blog.csdn.net/qq_41418281/article/details/105376914