analysis
题目意思就是以各种方式给你一个9x9的数独让你填
然后数据是各种鬼畜
这个时候考虑一个很简单的搜索框架:就是找一个位置的可能数,然后暴力的dfs
然后考虑剪枝和优化:
想要优化这个算法,想了一个策略:找可选的数最少的一个
但是如何统计可选的数呢,用数组?统计一次就O(n)未必太慢了,用状态压缩的方法就可以,因为这里的数据范围是这样的小
我们可以用状态压缩表示每行每列每个九宫格的数字选取情况,但是有没有什么办法能够让我们快速的找到当前位置可以选的数呢?这个时候就有一个比较好的方法,就是在表示选取状况的时候,如果有这个数,就表示为0,反之表示为1,这样的话就可以用&运算来取得没有选的数的集合了,在加上lowbit,简直快的不要不要的,时间复杂度就是O(1)
但为了选取候选数最少的那个,我们还需要快速算出当前二进制集合里面1的个数
并且我们还要把当前二进制下选的数转化成10进制(100=>3)
于是想到,可以预处理数组,这个问题就迎刃而解
于是就可以过了
具体实现的时候要注意一个问题:1<<x是指将1左移x位,也就是说单纯的1是1<<0而非1<<1,所以这个时候最好用0基准来写代码
#include <iostream>
#include <fstream>
#include <cstdio>
#include <cmath>
#include <map>
#include <set>
#include <bitset>
#include <ctime>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#include <vector>
using namespace std;
#define loop(i,start,end) for(int i=start;i<=end;++i)
#define anti_loop(i,start,end) for(int i=start;i>=end;--i)
#define clean(arry,num) memset(arry,num,sizeof(arry))
#define ll long long
template<typename T>void read(T &x){
x=0;char r=getchar();T neg=1;
while(r>'9'||r<'0'){if(r=='-')neg=-1;r=getchar();}
while(r>='0'&&r<='9'){x=(x<<1)+(x<<3)+r-'0';r=getchar();}
x*=neg;
}
#define lowbit(x) (x&(-x))
int T;
char s[100];
inline bool readsd(){
int cnt=0;char r;
while(1){
if(cnt>=81)break;
r=getchar();
if(r>='0'&&r<='9')s[cnt++]=r;
else if(r=='.')s[cnt++]='0';
else if(r=='e')return false;
}
return true;
}
int x[15],y[15],z[15];
int posx,posy,posz;
int cnt[(1<<10)+10];
int f[(1<<10)+10];
inline void getpos(int _x){
posx=(_x)/9;
posy=(_x)%9;
posz=(posx/3)*3+posy/3;
}
inline void turn(int _x,int w){
getpos(_x);
--w;
x[posx]^=(1<<w);
y[posy]^=(1<<w);
z[posz]^=(1<<w);
}
bool dfs(int pos){
if(!pos)
return true;
int bestpos=0,minn=10;
loop(i,0,80){
if(s[i]=='0'){
getpos(i);
int _w=x[posx]&y[posy]&z[posz];
if(minn>cnt[_w]){
minn=cnt[_w];
bestpos=i;
}
}
}
getpos(bestpos);
int w_=x[posx]&y[posy]&z[posz];
while(w_){
int num=f[lowbit(w_)]+1;
s[bestpos]=num+'0';
turn(bestpos,num);
if(dfs(pos-1))
return true;
s[bestpos]='0';
turn(bestpos,num);
w_-=lowbit(w_);
}
return false;
}
inline int count_(int x){
int res=0;
while(x){
x-=lowbit(x);
++res;
}
return res;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("datain.txt","r",stdin);
#endif
while(readsd()){
int nfz=81;
loop(i,0,9)
x[i]=y[i]=z[i]=(1<<9)-1,
f[1<<i]=i;
loop(i,0,80)
if(s[i]!='0')
turn(i,s[i]-'0'),
--nfz;
loop(i,0,(1<<9))
cnt[i]=count_(i);
if(!dfs(nfz)){
printf(">>>>>>>>>>>WA\n");
continue;
}
loop(i,0,80)
printf("%c",s[i]);
printf("\n");
}
return 0;
}