蓝桥杯 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;
相关推荐
轻抚酸~几秒前
KNN(K近邻算法)-python实现
python·算法·近邻算法
测试界的海飞丝1 小时前
10道软件测试面试题及其答案:
服务器·测试工具·职场和发展
Yue丶越2 小时前
【C语言】字符函数和字符串函数
c语言·开发语言·算法
小白程序员成长日记3 小时前
2025.11.24 力扣每日一题
算法·leetcode·职场和发展
有一个好名字3 小时前
LeetCode跳跃游戏:思路与题解全解析
算法·leetcode·游戏
爱学习的小邓同学3 小时前
C++ --- 多态
开发语言·c++
AndrewHZ3 小时前
【图像处理基石】如何在图像中提取出基本形状,比如圆形,椭圆,方形等等?
图像处理·python·算法·计算机视觉·cv·形状提取
蓝牙先生4 小时前
简易TCP C/S通信
c语言·tcp/ip·算法
xiaoye-duck6 小时前
计数排序:高效非比较排序解析
数据结构
稚辉君.MCA_P8_Java7 小时前
Gemini永久会员 Java中的四边形不等式优化
java·后端·算法