·【蓝桥】·九宫幻方

本题考查的是…计算思维吧

题目来源:
青蛙跳杯子

问题描述
  小明最近在教邻居家的小朋友小学奥数,而最近正好讲述到了三阶幻方这个部分,三阶幻方指的是将1~9不重复的填入一个33的矩阵当中,使得每一行、每一列和每一条对角线的和都是相同的。
  三阶幻方又被称作九宫格,在小学奥数里有一句非常有名的口诀:“二四为肩,六八为足,左三右七,戴九履一,五居其中”,通过这样的一句口诀就能够非常完美的构造出一个九宫格来。
  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
数据规模和约定
  峰值内存消耗(含虚拟机) < 256M
  CPU消耗 < 1000ms

题目分析

  1. 观察可以发现,3*3矩阵满足三阶幻方的仅8中组合:

    1
    2
    3
    4
    5
    6
    7
    8
    int v[8][9] = {{4,9,2,3,5,7,8,1,6},
    {2,9,4,7,5,3,6,1,8},
    {2,7,6,9,5,1,4,3,8},
    {6,7,2,1,5,9,8,3,4},
    {8,1,6,3,5,7,4,9,2},
    {6,1,8,7,5,3,2,9,4},
    {4,3,8,9,5,1,2,7,6},
    {8,3,4,1,5,9,6,7,2}};
  2. 对于测试输入,只需和这8种组合依次比较,满足其中仅一组符合,说明可以还原
    其他情况都是“Too Many”,判断的时候使用flag、ans两个变量标记

————————————————完整代码——————————————————

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>

using namespace std;

int v[8][9] = {{4,9,2,3,5,7,8,1,6},
{2,9,4,7,5,3,6,1,8},
{2,7,6,9,5,1,4,3,8},
{6,7,2,1,5,9,8,3,4},
{8,1,6,3,5,7,4,9,2},
{6,1,8,7,5,3,2,9,4},
{4,3,8,9,5,1,2,7,6},
{8,3,4,1,5,9,6,7,2}};
int judge(int a[]){
int flag = 0, ans = -1; //flag标记可行解,ans确保可行解仅一组
for(int i = 0; i < 8; ++i){
flag = 0;
for(int j = 0; j < 9; ++j){
if(a[j] == 0)
continue;
if(a[j] != v[i][j])
flag = 1;
}
if(flag == 0){
if(ans == -1)
ans = i;
else
ans = -1;
}
}
return ans;
}
int main(){
int a[9];
for(int i = 0; i < 9; ++i){
scanf("%d", &a[i]);
}
if(judge(a) != -1){ //当且仅当返回值不为-1,仅有一组可行解
int j = judge(a);
for(int i = 0; i < 9; ++i){
if(i%3 == 2)
printf("%d\n", v[j][i]);
else
printf("%d ", v[j][i]);
}
}else
printf("Too Many\n");
return 0;
}

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!