https://loj.ac/problem/2591
题目描述
给出数独的一部分,并且每个位置的有一定分数,数独的总分数等于所有位置上的数值乘以其分数,求最大分数
思路
首先直接爆搜肯定会(T)掉,我们就需要贪心的从一种较优解开始搜索。我采用的是一种较优的方法,先统计一遍每行已知的个数,然后在将行排序一遍,从已知数字最多的那一行逐列搜索,全部搜索完后统计答案即可。注意维护数独的各个信息就可以了。
代码
#include <bits/stdc++.h>
using namespace std;
int mp[10][10];
bool l[10][10],h[10][10],jg[10][10];
int ans;
int v[15][15]={{},{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}};
bool f;
struct Node
{
int l,sum;
}ll[20];
int cmp(Node a,Node b)
{
return a.sum<b.sum;
}
int change(int a,int b)
{
return (b-1)/3+(a-1)/3*3+1;
}
void dfs(int x,int y,int ha)
{
if(ha==10)
{
f=1;
int sum=0;
for(int i=1;i<=9;i++)
for(int j=1;j<=9;j++)
sum+=mp[i][j]*v[i][j];
ans=max(ans,sum);
return ;
}
if(y==10)
{
dfs(ll[ha+1].l,1,ha+1);
return ;
}
if(!mp[x][y])
{
for(int num=1;num<=9;num++)
if(!h[x][num]&&!l[y][num]&&!jg[change(x,y)][num])
{
mp[x][y]=num;h[x][num]=1;l[y][num]=1;jg[change(x,y)][num]=1;
dfs(x,y+1,ha);
mp[x][y]=0;h[x][num]=0;l[y][num]=0;jg[change(x,y)][num]=0;
}
}
else dfs(x,y+1,ha);
}
int main()
{
for(int i=1;i<=9;i++)
{
int s=0;
for(int j=1;j<=9;j++)
{
int a;
scanf("%d",&a);
if(!a)s++;
mp[i][j]=a;h[i][a]=1;l[j][a]=1;
jg[change(i,j)][a]=1;
}
ll[i].l=i;ll[i].sum=s;
}
sort(ll+1,ll+10,cmp);
dfs(ll[1].l,1,1);
if(f)printf("%d",ans);
else printf("-1");
return 0;
}