三阶幻方指的是将1~9不重复的填入一个3*3的矩阵当中,使得每一行、每一列和每一条对角线的和都是相同的。例如:
4 9 2
3 5 7
8 1 6
有意思的是,所有的三阶幻方,都可以通过这样一个九宫格进行若干镜像和旋转操作之后得到。
输入:
输入仅包含单组测试数据。
输入的测试数据为一个3*3的矩阵,其中为0的部分表示被抹去的部分。
对于100%的数据,满足给出的矩阵至少能还原出一组可行的三阶幻方。
输出:
如果仅能还原出一组可行的三阶幻方,则将其输出,否则输出“Too Many”(不包含引号)。
Java:
package easy;
//import java.util.Date;
import java.util.Scanner;
public class Number_n {
static int[] num = new int[10];
static int[] result = new int[10];
static boolean[] bool = new boolean[10];
static boolean[] flag = new boolean[10]; //初始输入九宫格中数字i是否被使用了
public static int count = 0;
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
for(int i = 1;i < 10;i++){
num[i] = input.nextInt();
flag[num[i]] = true;
}
f(1);
input.close();
if(count == 1){
System.out.println(result[1]+ " " +result[2]+ " " +result[3]);
System.out.println(result[4]+ " " + result[5]+ " " +result[6]);
System.out.println(result[7]+ " " + result[8]+ " " +result[9]);
}
else if(count == 0)
System.out.println("Zero!");
else
System.out.println("Too Many!");
}
public static void f(int step){
if(step == 10){
int a = num[1] + num[2] +num[3];
int b = num[4] + num[5] +num[6];
int c = num[7] + num[8] +num[9];
int d = num[1] + num[4] +num[7];
int e = num[2] + num[5] +num[8];
int f = num[3] + num[6] +num[9];
int g = num[1] + num[5] +num[9];
int h = num[3] + num[5] +num[7];
if(a==b && a==c && a==d && a==e && a==f && a==g && a==h){
for(int p = 1;p < 10;p++){
result[p] = num[p];
}
count++;
}
else
return;
return;
}
if(num[step] != 0){
f(step+1);
return;
}
for(int i = 1;i < 10;i++){ //将数字1-9一次试着填入进为0的位置
if(!bool[i] && !flag[i] && num[step]==0){
bool[i] = true; //数字i此时已经被填入
num[step] = i;
f(step+1);
num[step] = 0;
bool[i] = false;
}
}
}
}
C++:
#include
int show(int *str,int *ch)
{
for(int j=0;j<9;j++)
{
if(str[j]==ch[j])continue;
if(ch[j]==0)continue;
if(str[j]!=ch[j])return 0;
}
return 1;
}
int main()
{
//1880: [蓝桥杯][2017年第八届真题]九宫幻方
/*
6 7 2 8 3 4 2 9 4 6 1 8
1 5 9 1 5 9 7 5 3 7 5 3
8 3 4 6 7 2 6 1 8 2 9 4
2 7 6 4 3 8 4 9 2 8 1 6
9 5 1 9 5 1 3 5 7 3 5 7
4 3 8 2 7 6 8 1 6 4 9 2
*/
int str[][9]={
{6,7,2,1,5,9,8,3,4},
{8,3,4,1,5,9,6,7,2},
{2,9,4,7,5,3,6,1,8},
{6,1,8,7,5,3,2,9,4},
{2,7,6,9,5,1,4,3,8},
{4,3,8,9,5,1,2,7,6},
{4,9,2,3,5,7,8,1,6},
{8,1,6,3,5,7,4,9,2},
};
int ch[9];
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
scanf("%d",&ch[i*3+j]);
}
int i,tmp=0;
for(int k=0;k<8;k++)
{
if(show(str[k],ch))
{
tmp+=1;
if(tmp==1)i=k;
}
}
if(tmp==1)
for(int j=0;j<9;j++)
{
if(j!=0 &&j%3==0)
printf("\n");
printf("%d ",str[i][j]);
}
else{
printf("Too Many");
}
return 0;
}
上面Java与C++两种语言不同的代码,正好是两种不同的解题思路
Java:
回溯法思想,一点一点判断,不对则进行回溯修改
C++:
将所有可能的结果存在数组中,将输入进来的九宫格和所有可能的结果一一进行比较