题目描述
小明最近在教邻居家的小朋友小学奥数,而最近正好讲述到了三阶幻方这个部分,三阶幻方指的是将1~9不重复的填入一个3*3的矩阵当中,使得每一行、每一列和每一条对角线的和都是相同的。
三阶幻方又被称作九宫格,在小学奥数里有一句非常有名的口诀:“二四为肩,六八为足,左三右七,戴九履一,五居其中”,通过这样的一句口诀就能够非常完美的构造出一个九宫格来。
4 9 2
3 5 7
8 1 6
有意思的是,所有的三阶幻方,都可以通过这样一个九宫格进行若干镜像和旋转操作之后得到。现在小明准备将一个三阶幻方(不一定是上图中的那个)中的一些数抹掉,交给邻居家的小朋友来进行还原,并且希望她能够判断出究竟是不是只有一个解。
而你呢,也被小明交付了同样的任务,但是不同的是,你需要写一个程序~
输入
输入仅包含单组测试数据。
每组测试数据为一个3*3的矩阵,其中为0的部分表示被小明抹去的部分。
对于100%的数据,满足给出的矩阵至少能还原出一组可行的三阶幻方。
输出
如果仅能还原出一组可行的三阶幻方,则将其输出,否则输出“Too Many”(不包含引号)。
样例输入
0 7 2
0 5 0
0 3 0
样例输出
6 7 2
1 5 9
小明最近在教邻居家的小朋友小学奥数,而最近正好讲述到了三阶幻方这个部分,三阶幻方指的是将1~9不重复的填入一个3*3的矩阵当中,使得每一行、每一列和每一条对角线的和都是相同的。
三阶幻方又被称作九宫格,在小学奥数里有一句非常有名的口诀:“二四为肩,六八为足,左三右七,戴九履一,五居其中”,通过这样的一句口诀就能够非常完美的构造出一个九宫格来。
4 9 2
3 5 7
8 1 6
有意思的是,所有的三阶幻方,都可以通过这样一个九宫格进行若干镜像和旋转操作之后得到。现在小明准备将一个三阶幻方(不一定是上图中的那个)中的一些数抹掉,交给邻居家的小朋友来进行还原,并且希望她能够判断出究竟是不是只有一个解。
而你呢,也被小明交付了同样的任务,但是不同的是,你需要写一个程序~
输入
输入仅包含单组测试数据。
每组测试数据为一个3*3的矩阵,其中为0的部分表示被小明抹去的部分。
对于100%的数据,满足给出的矩阵至少能还原出一组可行的三阶幻方。
输出
如果仅能还原出一组可行的三阶幻方,则将其输出,否则输出“Too Many”(不包含引号)。
样例输入
0 7 2
0 5 0
0 3 0
样例输出
6 7 2
1 5 9
8 3 4
分析:由于题目的九宫幻方的情况很少,所以我们可以预先求出来然后再去判断即可,那么一共有多少种情况呢?
我们可以这样考虑,将原来的矩阵经过旋转得到4种情况,我们只看一个数,比如是4,有4个位置,4的位置确定以后2的位置 自然也确定了,对称的话只需要将2旋转一下即可。那么一共4*2 = 8种情况。看代码:
import java.util.*;
public class Main {
static Scanner in = new Scanner(System.in);
static int[][] a = new int[3][3];
static int cnt,ans;
static String[] ss = {"492357816","834159672","618753294","276951438",
"438951276","294753618","672159834","816357492"};
public static void main(String[] args) {
String s = "";
for(int i = 0;i < 3;i++)
for(int j = 0;j < 3;j++) {
a[i][j] = in.nextInt();
s+=a[i][j];
}
boolean f = false;
for(int i = 0;i < 8;i++) {
f = false;
for(int j = 0;j < 8;j++) {
if((ss[i].charAt(j)==s.charAt(j))||s.charAt(j)=='0')
continue;
if(ss[i].charAt(j)!=s.charAt(j)) {
f = true;break;
}
}
if(!f) {
cnt++;
ans = i;
}
}
if(cnt==1) {
for(int i = 0;i < 9;i+=3)
for(int j = i;j < i + 3;j++) {
if(j!=i+2)
System.out.print(ss[ans].charAt(j)+" ");
else
System.out.println(ss[ans].charAt(j));
}
}else
System.out.println("Too Many");
}
}
思考:其实可以用用暴搜直接判断即可,看代码:
import java.util.*;
public class Main {
static Scanner in = new Scanner(System.in);
static int[][] a = new int[3][3];
static int[] b = new int[10];
static int[] c = new int[10];
static int maxn = 9,ans = 0;
static void dfs(int sp) {//全排列
if(sp>=maxn) {
boolean f = true ;
for(int i = 0;i < 3;i++)
for(int j = 0;j < 3;j++) {
if(a[i][j]!=0&&b[i*3+j]!=a[i][j])//对应位置不正确
f = false;
}
if(f) {//判断每一行和是否相同
for(int i = 0;i < 3;i++) {
int sum = 0;
for(int j = 0;j < 3;j++)
sum+=b[i*3+j];
if(sum!=15) {
f = false;break;
}
}
}
if(f) {//判断每一列和是否相同
for(int j = 0;j < 3;j++) {
int sum = 0;
for(int i = 0;i < 3;i++)
sum+=b[i*3+j];
if(sum!=15) {
f = false;break;
}
}
}
if(b[0]+b[4]+b[8]!=15||b[2]+b[4]+b[6]!=15)//对角线
f = false;
if(f) {
ans++;
for(int i = 0;i < maxn;i++)
c[i] = b[i];
return;
}
}
for(int i = sp;i <= maxn;i++) {//交换思想,可以看我写过的全排列的文章
int t = b[sp];b[sp] = b[i];b[i] = t;
dfs(sp+1);
t = b[sp];b[sp] = b[i];b[i] = t;
}
}
public static void main(String[] args) {
for(int i = 1;i <= maxn;i++)
b[i] = i;
for(int i = 0;i < 3;i++)
for(int j = 0;j < 3;j++) {
a[i][j] = in.nextInt();
}
long s = System.currentTimeMillis();
dfs(0);
if(ans>1)
System.out.println("Too Many");
else {
for(int i = 0;i < 3;i++)
for(int j = 0;j < 3;j++) { //注意控制格式输出
if(j!=2)
System.out.print(c[i*3+j]+" ");
else
System.out.println(c[i*3+j]);
}
}
long e = System.currentTimeMillis();
System.out.println(e-s);//计算程序运行时间(毫秒)
}
}
但是时间复杂度的话肯定是要高很多了,可以对比一下程序运行时间。