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;
}