蓝桥杯 9. 九宫幻方

九宫幻方

原题目链接

题目描述

小明最近在教邻居家的小朋友小学奥数,而最近正好讲述到了三阶幻方这个部分。

三阶幻方 是指将 1 ~ 9 不重复地填入一个 3×3 的矩阵中,使得每一行、每一列和每一条对角线的和都是相同的。

三阶幻方又被称作九宫格,在小学奥数里有一句非常有名的口诀:

"二四为肩,六八为足,左三右七,戴九履一,五居其中"

通过这句口诀,可以构造出一个标准九宫格,如下:

in 复制代码
4 9 2  
3 5 7  
8 1 6  

有意思的是,所有的三阶幻方 ,都可以通过这个标准九宫格进行若干次镜像和旋转操作之后得到。


任务

现在小明将一个三阶幻方(不一定是标准形)中的一些数抹掉,交给邻居家的小朋友来进行还原,并希望她判断是否只有唯一解

你也被小明交付了同样的任务------写一个程序完成这个判断。


输入描述

输入仅包含一组测试数据,为一个 3×3 的矩阵。矩阵中的数为 0 表示该位置的数被抹掉。

保证输入的矩阵至少可以还原出一组可行的三阶幻方。


输出描述

  • 如果仅能还原出一组可行的三阶幻方,则将该幻方输出,按矩阵形式每行一个空格分隔的整数。
  • 否则,输出 "Too Many"(不含引号)。

输入样例

in 复制代码
0 7 2
0 5 0
0 3 0

输出样例

out 复制代码
6 7 2
1 5 9
8 3 4

c++代码

cpp 复制代码
#include<bits/stdc++.h>

using namespace std;

vector<vector<int>> arr(3, vector<int>(3)), ans;
vector<bool> know(10, true);
int cont = 0, sum = 0;

void dfs(int i, int j) {
    if (cont >= 2 || i < 0 || i > 3 || j < 0 || j >= 3) return;
    if (i == 3) {
        sum = arr[0][0] + arr[1][1] + arr[2][2];
        if (sum != arr[0][2] + arr[1][1] + arr[2][0]) return;
        for (int i = 0; i < 3; i++) {
            int mid = 0;
            for (int j = 0; j < 3; j++) mid += arr[i][j];
            if (mid != sum) return;
        }
        for (int j = 0; j < 3; j++) {
            int mid = 0;
            for (int i = 0; i < 3; i++) mid += arr[i][j];
            if (mid != sum) return;
        }
        cont++;
        ans = arr;
        return;
    }
    int x, y;
    if (j == 2) x = i + 1, y = 0;
    else x = i, y = j + 1;
    if (arr[i][j] != 0) dfs(x, y);
    else {
        for (int k = 1; k <= 9; k++) {
            if (!know[k]) continue;
            know[k] = false;
            arr[i][j] = k;
            dfs(x, y);
            arr[i][j] = 0;
            know[k] = true;
        }
    }
}

int main() {
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            cin >> arr[i][j];
            if (arr[i][j] != 0) know[arr[i][j]] = false;
        }
    }
    dfs(0, 0);
    if (cont == 1) {
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                if (j == 2 && i != 2) cout << ans[i][j] << endl;
                else cout << ans[i][j] << " ";
            }
        }
    }
    else cout << "Too Many";
    return 0;
}//by wqs

思路解析

每个数字只能出现一次,要记录哪些数字被选择了,我们只能选择没有被选择的数字。

cpp 复制代码
if (arr[i][j] != 0) know[arr[i][j]] = false;

暴力枚举每个格子可能的数字就行。

cpp 复制代码
for (int k = 1; k <= 9; k++) {
    if (!know[k]) continue;
    know[k] = false;
    arr[i][j] = k;
    dfs(x, y);
    arr[i][j] = 0;
    know[k] = true;
}

枚举完之后判断是否满足每一行、每一列和每一条对角线的和都是相同的。

cpp 复制代码
sum = arr[0][0] + arr[1][1] + arr[2][2];
if (sum != arr[0][2] + arr[1][1] + arr[2][0]) return;
for (int i = 0; i < 3; i++) {
    int mid = 0;
    for (int j = 0; j < 3; j++) mid += arr[i][j];
    if (mid != sum) return;
}
for (int j = 0; j < 3; j++) {
    int mid = 0;
    for (int i = 0; i < 3; i++) mid += arr[i][j];
    if (mid != sum) return;
}

记录符合条件的数目,如果大于2直接跳出dfs函数,防止超时。

cpp 复制代码
if (cont >= 2 || i < 0 || i > 3 || j < 0 || j >= 3) return;
相关推荐
NAGNIP1 分钟前
一文搞懂机器学习中的特征降维!
算法·面试
NAGNIP17 分钟前
一文搞懂机器学习中的特征构造!
算法·面试
Learn Beyond Limits44 分钟前
解构语义:从词向量到神经分类|Decoding Semantics: Word Vectors and Neural Classification
人工智能·算法·机器学习·ai·分类·数据挖掘·nlp
你怎么知道我是队长1 小时前
C语言---typedef
c语言·c++·算法
带土12 小时前
5. enum(枚举)关键字在C/C++中的作用
c语言·c++
驴友花雕2 小时前
【花雕学编程】Arduino BLDC 之群体机器人协同探索
c++·单片机·嵌入式硬件·arduino bldc·群体机器人协同探索
驴友花雕2 小时前
【花雕学编程】Arduino BLDC 之仿人机器人膝关节稳定系统
c++·单片机·嵌入式硬件·arduino bldc·仿人机器人膝关节稳定系统
Qhumaing2 小时前
C++学习:【PTA】数据结构 7-1 实验7-1(最小生成树-Prim算法)
c++·学习·算法
Z1Jxxx4 小时前
01序列01序列
开发语言·c++·算法