题面:
题解:
与正常的数独一样,不过这个并不是跑出一个解来即可,需要所有解取最大值。
既然是最大值,那么肯定可以最优性剪枝,不过不剪也能过,就没剪。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int a[10][10];
int row[9],col[9],grid[9],cnt[512],num[512],tot;
int maxx=-1;
const int c[10][10]=
{
{6,6,6,6,6,6,6,6,6},
{6,7,7,7,7,7,7,7,6},
{6,7,8,8,8,8,8,7,6},
{6,7,8,9,9,9,8,7,6},
{6,7,8,9,10,9,8,7,6},
{6,7,8,9,9,9,8,7,6},
{6,7,8,8,8,8,8,7,6},
{6,7,7,7,7,7,7,7,6},
{6,6,6,6,6,6,6,6,6}
};
int g(int x, int y)//得到九宫格的哪一个
{
return ((x/3)*3)+(y/3);
}
inline void flip(int x, int y, int z) //更新当前状态和还原现场
{
row[x]^=1<<z;
col[y]^=1<<z;
grid[g(x, y)]^=1<<z;
}
void dfs(int now,int ans)
{
if (now==0) //填完了
{
maxx=max(maxx,ans);
return ;
}
int temp=10,x,y;
for (int i=0;i<9;i++)
for (int j=0;j<9;j++)
{
if(a[i][j]!= 0) continue;
int val=row[i]&col[j]&grid[g(i, j)];//能填的数
if(!val) return ;//没有能填的数
if(cnt[val]<temp) //当前位置能填的数的个数
{
temp=cnt[val];
x=i,y=j;
}
}
int val=row[x]&col[y]&grid[g(x, y)];//得到能填的数
for( ;val;val-=val&-val)
{
int z=num[val&-val];//第几位
a[x][y]=1+z;//更新当前状态
flip(x,y,z);
dfs(now-1,ans+c[x][y]*a[x][y]);
flip(x,y,z);//还原现场
a[x][y] = 0;
}
return ;
}
int main()
{
for(int i=0;i<(1<<9);i++)//预处理i状态1的个数
for(int j=i;j;j-=j&-j) cnt[i]++;
for (int i=0;i<9;i++)//预处理第几位
num[1<<i] = i;
for(int i=0;i<9;i++)
for(int j=0;j<9;j++)
scanf("%d",&a[i][j]);
for (int i=0;i<9;i++) //全部初始化为可填。
row[i]=col[i]=grid[i]=(1 << 9)-1;
tot=0;//需要填的个数
int ans=0;
for(int i=0;i<9;i++)
for (int j=0;j<9;j++)
if (a[i][j] != 0) flip(i,j,a[i][j]-1),ans+=a[i][j]*c[i][j];//把行列九宫格不能填的去掉。
else tot++;
dfs(tot,ans);
printf("%d\n",maxx);
return 0;
}