蓝桥杯 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;
相关推荐
又是忙碌的一天1 分钟前
二叉树的构建与增删改查(2) 删除节点
数据结构
Code Slacker15 分钟前
LeetCode Hot100 —— 滑动窗口(面试纯背版)(四)
数据结构·c++·算法·leetcode
brave and determined19 分钟前
CANN训练营 学习(day8)昇腾大模型推理调优实战指南
人工智能·算法·机器学习·ai实战·昇腾ai·ai推理·实战记录
总爱写点小BUG1 小时前
打印不同的三角形(C语言)
java·c语言·算法
yaoh.wang1 小时前
力扣(LeetCode) 27: 移除元素 - 解法思路
python·程序人生·算法·leetcode·面试·职场和发展·双指针
2401_841495641 小时前
【自然语言处理】中文 n-gram 词模型
人工智能·python·算法·自然语言处理·n-gram·中文文本生成模型·kneser-ney平滑
San302 小时前
从零到一:彻底搞定面试高频算法——“列表转树”与“爬楼梯”全解析
javascript·算法·面试
F_D_Z2 小时前
最长连续序列(Longest Consecutive Sequence)
数据结构·算法·leetcode
ss2732 小时前
Java并发编程:DelayQueue延迟订单系统
java·python·算法
SHERlocked932 小时前
摄像头 RTSP 流视频多路实时监控解决方案实践
c++·后端·音视频开发