题解:P1074 [NOIP2009 提高组] 靶形数独
DiaoHantong · · 题解
题目传送门
思路
本题要求出数独的所有解法,在所有解中找最大值,所以搜索量巨大。显然的优化思路是优先选择限制条件多的位置填写。比如某行已经填了
代码
#include<bits/stdc++.h>
using namespace std;
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[10][10],col[10][10],grid[10][10],a[10][10];
int row_cnt[10],col_cnt[10],cnt,ans=-1;
int tran(int x,int y){
return (x-1)/3*3+(y-1)/3+1;
}
int calc(){
int tmp=0;
for(int i=1;i<=9;i++)
for(int j=1;j<=9;j++)
tmp+=score[i][j]*a[i][j];
return tmp;
}
void dfs(int x,int y,int tot){
if(tot==81){
ans=max(ans,calc());
return;
}
for(int i=1;i<=9;i++){
if(row[x][i]||col[y][i]||grid[tran(x,y)][i])continue;
row[x][i]=col[y][i]=grid[tran(x,y)][i]=true;
row_cnt[x]++,col_cnt[y]++;
a[x][y]=i;
int tmpr=-1,nxt_x=0,tmpc=-1,nxt_y=0;
for(int j=1;j<=9;j++)
if(row_cnt[j]>tmpr&&row_cnt[j]<9)
tmpr=row_cnt[j],nxt_x=j;
for(int j=1;j<=9;j++)
if(col_cnt[j]>tmpc&&!(a[nxt_x][j]))
tmpc=col_cnt[j],nxt_y=j;
dfs(nxt_x,nxt_y,tot+1);
row[x][i]=col[y][i]=grid[tran(x,y)][i]=false;
row_cnt[x]--,col_cnt[y]--;
a[x][y]=0;
}
}
int main(){
for(int i=1;i<=9;i++){
for(int j=1;j<=9;j++){
cin>>a[i][j];
if(a[i][j]!=0){
row[i][a[i][j]]=true;
col[j][a[i][j]]=true;
grid[tran(i,j)][a[i][j]]=true;
row_cnt[i]++,col_cnt[j]++;
cnt++;//已经填了的数量
}
}
}
int tmpr=-1,x,tmpc=-1,y;
for(int j=1;j<=9;j++)
if(row_cnt[j]>tmpr&&row_cnt[j]<9)
tmpr=row_cnt[j],x=j;//选已填数最多的行x出发
for(int j=1;j<=9;j++)
if(col_cnt[j]>tmpc&&(!a[x][j]))
tmpc=col_cnt[j],y=j;//选行x里填数最多的列y出发
dfs(x,y,cnt);
cout<<ans;
return 0;
}