深搜+剪枝,求出得分。
剪枝:已知数多的地方先填
#include
#include
#include
using namespace std;
int in(){
char c=getchar(); int ans=0;
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
const int MAXN=11;
const int score[10][10]={{0,0,0,0,0,0,0,0,0,0},{0,6,6,6,6,6,6,6,6,6},{0,6,7,7,7,7,7,7,7,6},{0,6,7,8,8,8,8,8,7,6},{0,6,7,8,9,9,9,8,7,6},{0,6,7,8,9,10,9,8,7,6},{0,6,7,8,9,9,9,8,7,6},{0,6,7,8,8,8,8,8,7,6},{0,6,7,7,7,7,7,7,7,6},{0,6,6,6,6,6,6,6,6,6}};
int row[MAXN][MAXN],col[MAXN][MAXN],area[MAXN][MAXN],sdk[MAXN][MAXN];
int row_cnt[MAXN],col_cnt[MAXN],cnt,ans=-1;
inline int id(int i,int j){return (i-1)/3*3+1+(j-1)/3;}
inline int calc(){
int tmp=0;
for(int i=1;i<=9;++i)
for(int j=1;j<=9;++j)
tmp+=score[i][j]*sdk[i][j];
return tmp;
}
void dfs(int r,int c,int cpl){
if(cpl==81){//填满
ans=max(ans,calc());//记录最大答案
return ;
}
for(int k=1;k<=9;++k){
if(row[r][k]||col[c][k]||area[id(r,c)][k]) continue;//重复了
row[r][k]=true;
col[c][k]=true;
area[id(r,c)][k]=true;
row_cnt[r]++,col_cnt[c]++;
sdk[r][c]=k;
int tmpr=-1,nxt_r=0,tmpc=-1,nxt_c=0;
for(int i=1;i<=9;++i)
if(row_cnt[i]>tmpr&&row_cnt[i]<9)
tmpr=row_cnt[i],nxt_r=i;
for(int j=1;j<=9;++j)
if(col_cnt[j]>tmpc&&(!sdk[nxt_r][j]))
tmpc=col_cnt[j],nxt_c=j;
dfs(nxt_r,nxt_c,cpl+1);//下一个地方
row[r][k]=false;//回溯
col[c][k]=false;
area[id(r,c)][k]=false;
row_cnt[r]--,col_cnt[c]--;
sdk[r][c]=0;
}
}
int main(){
for(int i=1;i<=9;++i){
for(int j=1;j<=9;++j){
sdk[i][j]=in();
if(sdk[i][j]!=0){//已知数
row[i][sdk[i][j]]=true;//行
col[j][sdk[i][j]]=true;//列
area[id(i,j)][sdk[i][j]]=true;//宫
row_cnt[i]++,col_cnt[j]++;//行列已知数个数增加
cnt++;//已知数个数增加
}
}
}
int tmpr=-1,r,tmpc=-1,c;
for(int i=1;i<=9;++i)
if(row_cnt[i]>tmpr&&row_cnt[i]<9)
tmpr=row_cnt[i],r=i;
for(int j=1;j<=9;++j)
if(col_cnt[j]>tmpc&&(!sdk[r][j]))
tmpc=col_cnt[j],c=j;
dfs(r,c,cnt);//从最好填的地方开始
printf("%d",ans);
return 0;
}