靶形数独,一道搜索能做出来的题,数独相信大家都会,靶形数独就是给它加个权,然后搞一个和A*差不多的东西? 有几个剪枝:第一是如果现在的val加上剩余的格子弄最大的数,占最大的权都不如现在的ans,就属于根本扶不起来的,就return;还有就是在所有格子中找一个格子,让它可以填的情况最少,那么如果是这样需要枚举的次数就会减少。然后就水过了。。
//Writer : Hsz %WJMZBMR %tourist %hzwer
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#include<stack>
#include<vector>
#include<cstdlib>
#include<algorithm>
#define LL long long
using namespace std;
int g[10][10],ans,tot=81;
bool hang[10][10],lie[10][10],kuai[10][10];
bool flag;
int v[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 ju[10][10]= {//打表*2
0,0,0,0,0,0,0,0,0,0,
0,1,1,1,2,2,2,3,3,3,
0,1,1,1,2,2,2,3,3,3,
0,1,1,1,2,2,2,3,3,3,
0,4,4,4,5,5,5,6,6,6,
0,4,4,4,5,5,5,6,6,6,
0,4,4,4,5,5,5,6,6,6,
0,7,7,7,8,8,8,9,9,9,
0,7,7,7,8,8,8,9,9,9,
0,7,7,7,8,8,8,9,9,9,
};
void dfs(int rest,int val) {
if(rest==0) {
ans=max(ans,val);
// cout<<ans;
flag=1;//判没有解的情况
return;
}
if(rest*9*10+val<=ans) return;
int way=0,mn=10,tx=0,ty=0,bc;
for(int i=1; i<=9; i++)
for(int j=1; j<=9; j++) {
if(!g[i][j]) {
way=9;
bc=ju[i][j];
for(int k=1; k<=9; k++) {
if(hang[i][k]||lie[j][k]||kuai[bc][k]) way--;//找那个最少可能的点。
}
if(mn>way) mn=way,tx=i,ty=j;
}
}
int tc=ju[tx][ty];
int i=tx,j=ty;
for(int w=1; w<=9; w++)
if(!hang[i][w]&&!lie[j][w]&&!kuai[ju[i][j]][w]&&!g[i][j]) {
hang[i][w]=1;
lie[j][w]=1;
kuai[ju[i][j]][w]=1;
g[i][j]=w;
dfs(rest-1,val+w*v[i][j]);
hang[i][w]=lie[j][w]=kuai[ju[i][j]][w]=g[i][j]=0;
}
}
int main() {
for(int i=1; i<=9; i++)
for(int j=1; j<=9; j++) {
cin>>g[i][j];
if(g[i][j])
hang[i][g[i][j]]=1,
lie[j][g[i][j]]=1,
kuai[ju[i][j]][g[i][j]]=1,
--tot,
ans+=g[i][j]*v[i][j];
}
dfs(tot,ans);
if(flag)cout<<ans;else cout<<"-1";
return 0;
}