运用dfs算法
蒜头君天资聪颖,酷爱数学,尤其擅长做数独游戏。不过普通的数独游戏已经满足不了蒜头君了,于是他发明了一种“金字塔数独”:
下图即为金字塔数独。和普通数独一样,在9×9的大九宫格中有9个3×3的小九宫格(用粗黑色线隔开的)。要求每个格子上都有一个1到9的数字,每个数字在每个小九宫格内不能重复出现,每个数字在每行、每列也不能重复出现。
但金字塔数独的每一个格子都有一个分值,类似金字塔的俯视图。如图所示,白色格子为6分,蓝色格子为7分,绿色格子为8分,紫色格子为9分,红色格子为10分。颜色相同的格子分值一样,离中心越近则分值越高。
金字塔数独的总分等于每个格子上的数字和对应的分值乘积之和。现在蒜头君给定金字塔数独的若干数字,请问如何填写,可以使得金字塔数独的总分最高。
输入格式
输入一共9行。每行输入9个整数(每个数都在0—9的范围内),每两个整数之间用一个空格隔开,“0”表示该格子为空。
输出格式
输出为一行,输出一个整数,代表金字塔数独的最高总分。如果数独无解,则输出−1。
样例输入
0 0 0 0 0 0 0 0 0
0 0 3 0 0 0 9 0 0
7 9 0 0 0 2 0 1 3
0 0 9 1 5 0 0 0 0
0 7 4 0 2 6 1 3 9
0 0 6 0 0 0 0 0 0
6 0 0 0 0 7 0 0 0
3 1 0 4 0 5 7 9 6
0 0 7 0 0 1 0 4 0
样例输出
2864
public class Main {
static int [][]p=new int[10][10];
static int [][]l=new int[10][10];//行标记
static int [][]c=new int[10][10];//列标记
static int [][]pi=new int[10][10];//块标记
static int maxn;
static int sum1;
public static int score(int i,int j)
{
if(i==1||j==1||i==9||j==9)return 6;
if(i==2||j==2||i==8||j==8)return 7;
if(i==3||j==3||i==7||j==7)return 8;
if(i==4||j==4||i==6||j==6)return 9;
return 10;
}
static void dfs(int step,int sum)
{
if(step==sum1)
{
maxn=max(maxn,sum);
return ;
}
for(int i=9;i>=1;i--)
{
for(int j=9;j>=1;j--)
{
if(p[i][j]!=0)
continue;
for(int k=1;k<=9;k++)
{
int x,y,z ;
x=(i-1)/3;
y=(j-1)/3;
z=x*3+y+1;
if(l[i][k]==0&&c[j][k]==0&&pi[z][k]==0)
{
p[i][j]=k;
l[i][k]=1;
c[j][k]=1;
pi[z][k]=1;
step++;
dfs(step,sum+score(i,j)*k);
p[i][j]=0;
step--;
l[i][k]=0;
c[j][k]=0;
pi[z][k]=0;
}
}
return ;
}
}
return ;
}
private static int max(int maxn2, int sum) {
if (sum<=maxn2) {
return maxn2;
}
else {
return sum;
}
}
public static void main(String[] args) {
int t,t1,t2;
int num=0;
int s1=0;
for(int i=1;i<=9;i++)
{
for(int j=1;j<=9;j++)
{
System.out.println(p[i][j]);
if(p[i][j]==0)
{
t1=(i-1)/3;
t2=(j-1)/3;
t=t1*3+t2+1;
l[i][p[i][j]]=1;
c[j][p[i][j]]=1;
pi[t][p[i][j]]=1;
s1++;
num+=score(i,j)*p[i][j];
}
}
}
sum1=81-s1;
dfs(0,num);
if(maxn==0)
{System.out.println("");}
else
{System.out.println(maxn);}
}
}