洛谷:P2615
OJ: I4950
该代码使用了著名的 Siamese 方法(又称为 De la Loubère 方法)来生成奇数阶的幻方。该方法的核心思想是从幻方的第一行中间开始,按照特定的规则依次填入数字。
按四种规则生成神奇的幻方(二维数组)
代码实现:
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 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | /**************************************************************** * Description: 2015_S_semi_1 神奇的幻方 * Author: Alex Li * Date: 2024-09-16 09:43:16 * LastEditTime: 2024-09-19 14:36:36 ****************************************************************/ #include <iostream> #include <vector> using namespace std; int main() { int n; cin >> n; // 读取输入的 n,代表幻方的尺寸 // 定义 MagicSqure 数组,用于存储每个数字在幻方中的位置,大小为 n*n + 1,索引从 1 开始 vector<pair<int, int>> MagicSqure(n * n + 1); // 定义 squ 二维矩阵,用于存储最终的幻方,大小为 n×n,初始化为 0 vector<vector<int>> squ(n + 1, vector<int>(n + 1, 0)); // 初始化第一个数字 1 的位置,行位置为 0,列位置为 (n-1)/2,即中间位置 MagicSqure[1].first = 0; MagicSqure[1].second = (n - 1) / 2; // 将数字 1 填入 squ 数组对应的位置 squ[MagicSqure[1].first][MagicSqure[1].second] = 1; // 从数字 2 开始,按照题目要求的规则,逐个填入 squ 中 for (int i = 2; i <= n * n; i++) { // 情况 1:如果上一个数字 (i-1) 在第一行,但不在最后一列,则将当前数字填在最后一行,上一列的右一列 if (MagicSqure[i - 1].first == 0 && MagicSqure[i - 1].second != n - 1) { MagicSqure[i].first = n - 1; MagicSqure[i].second = MagicSqure[i - 1].second + 1; squ[MagicSqure[i].first][MagicSqure[i].second] = i; } // 情况 2:如果上一个数字 (i-1) 不在第一行,但在最后一列,则将当前数字填在第一列,上一行 else if (MagicSqure[i - 1].first != 0 && MagicSqure[i - 1].second == n - 1) { MagicSqure[i].first = MagicSqure[i - 1].first - 1; MagicSqure[i].second = 0; squ[MagicSqure[i].first][MagicSqure[i].second] = i; } // 情况 3:如果上一个数字 (i-1) 在第一行且在最后一列,则将当前数字填在 (i-1) 的正下方 else if (MagicSqure[i - 1].first == 0 && MagicSqure[i - 1].second == n - 1) { MagicSqure[i].first = MagicSqure[i - 1].first + 1; MagicSqure[i].second = MagicSqure[i - 1].second; squ[MagicSqure[i].first][MagicSqure[i].second] = i; } // 情况 4:如果上一个数字 (i-1) 既不在第一行也不在最后一列,尝试将当前数字填入右上方 else if (MagicSqure[i - 1].first != 0 && MagicSqure[i - 1].second != n - 1) { // 检查右上方是否已被占用 if (squ[MagicSqure[i - 1].first - 1][MagicSqure[i - 1].second + 1] == 0) { // 如果未被占用,则将当前数字填入右上方 MagicSqure[i].first = MagicSqure[i - 1].first - 1; MagicSqure[i].second = MagicSqure[i - 1].second + 1; squ[MagicSqure[i].first][MagicSqure[i].second] = i; } else { // 否则将当前数字填入正下方 MagicSqure[i].first = MagicSqure[i - 1].first + 1; MagicSqure[i].second = MagicSqure[i - 1].second; squ[MagicSqure[i].first][MagicSqure[i].second] = i; } } } // 输出最终构建的幻方 for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { cout << squ[i][j] << ' '; // 输出每个位置的数字 } cout << endl; // 每行输出结束后换行 } return 0; } |