NOIP基础算法(C++)-模拟算法例题3-神奇的幻方
NOIP基础算法(C++)-模拟算法例题3-神奇的幻方:
【题目描述】 幻方是一种很神奇的N*N矩阵:它由数字 1,2,3,......,N×N构成,且每行、每列及两条 对角线上的数字之和都相同。 当 N 为奇数时,我们可以通过下方法构建一个幻方: 首先将 1写在第一行的中间。 之后,按如下方式从小到大依次填写每个数 K(K=2,3,...,N×N): 1.若 (K-1)(在第一行但不在最后一列,则将 K 填在最后一行,(K-1)所在列的右一列; 2.若 (K-1) 在最后一列但不在第一行,则将 K填在第一列,(K-1) 所在行的上一行; 3.若 (K-1)在第一行最后一列,则将 K填在 (K-1) 的正下方; 4.若 (K-1) 既不在第一行,也最后一列,如果 (K-1)的右上方还未填数,则将K填在 (K-1) 的右上方,否则将 L填在(K-1) 的正下方。 现给定N,请按上述方法构造 N×N的幻方 输入格式: 一个正整数N,即幻方的大小。 输出格式: 共N行,每行N个整数,即按上述方法构造出的N*N幻方,相邻两个整数之间用单空格隔开。 输入样例: 3 输出样例: 8 1 6 3 5 7 4 9 2
方法一:
#include <iostream> #include <vector> using namespace std; // 生成幻方的函数 vector<vector<int> > generateMagicSquare(int n) { // 创建一个大小为N×N的二维向量,初始值都为0 vector<vector<int> > magicSquare(n, vector<int>(n, 0)); int row = 0; // 当前行的索引 int col = n / 2; // 当前列的索引 // 将数字1放在第一行的中间位置 magicSquare[row][col] = 1; // 依次填充数字2到N×N for (int num = 2; num <= n * n; num++) { // 检查(K-1)的位置 if (magicSquare[(row - 1 + n) % n][(col + 1) % n] == 0) { // 如果(K-1)的右上方还未填充数字,则将K放在右上方 row = (row - 1 + n) % n; col = (col + 1) % n; } else { // 否则将K放在(K-1)的正下方 row = (row + 1) % n; } // 填充数字K magicSquare[row][col] = num; } return magicSquare; } int main() { int n; cin >> n; // 读取输入的n // 生成幻方 vector<vector<int> > magicSquare = generateMagicSquare(n); // 打印幻方 for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { cout << magicSquare[i][j] << " "; } cout << endl; } return 0; }
这段代码首先定义了一个函数generateMagicSquare
,该函数接受一个整数n作为参数,返回一个N×N的幻方,其中N为输入的n的值。
在generateMagicSquare
函数中,我们首先创建一个大小为N×N的二维向量magicSquare
,并将其所有元素初始化为0。
接下来,我们使用两个变量row
和col
来追踪当前要填充的位置。我们将数字1放在第一行的中间位置,即row = 0
和col = n / 2
。然后,我们按照题目描述的规则填充剩余的数字。具体而言,对于数字K(从2到N×N),我们检查(K-1)的位置,并根据规则决定将K放置在哪个位置。如果(K-1)的右上方还未填充数字,则将K放在右上方,否则将K放在(K-1)的正下方。
最后,我们在main
函数中读取输入的n,调用generateMagicSquare
函数生成幻方,并将其打印出来。
请注意,这段代码假设输入的n是一个正整数,并且不会进行输入验证。在实际应用中,应该添加适当的输入验证和错误处理机制。
方法二:
#include <iostream> using namespace std; // 生成幻方的函数 int** generateMagicSquare(int n) { // 创建一个大小为N×N的二维动态数组,初始值都为0 int** magicSquare = new int*[n]; for (int i = 0; i < n; i++) { magicSquare[i] = new int[n]; for (int j = 0; j < n; j++) { magicSquare[i][j] = 0; } } int row = 0; // 当前行的索引 int col = n / 2; // 当前列的索引 // 将数字1放在第一行的中间位置 magicSquare[row][col] = 1; // 依次填充数字2到N×N for (int num = 2; num <= n * n; num++) { // 检查(K-1)的位置 if (magicSquare[(row - 1 + n) % n][(col + 1) % n] == 0) { // 如果(K-1)的右上方还未填充数字,则将K放在右上方 row = (row - 1 + n) % n; col = (col + 1) % n; } else { // 否则将K放在(K-1)的正下方 row = (row + 1) % n; } // 填充数字K magicSquare[row][col] = num; } return magicSquare; } int main() { int n; cin >> n; // 读取输入的n // 生成幻方 int** magicSquare = generateMagicSquare(n); // 打印幻方 for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { cout << magicSquare[i][j] << " "; } cout << endl; } // 释放动态数组内存 for (int i = 0; i < n; i++) { delete[] magicSquare[i]; } delete[] magicSquare; return 0; }
这段代码使用了动态数组代替了向量。在generateMagicSquare
函数中,我们使用new
运算符动态分配了一个大小为N×N的二维数组,并将所有元素初始化为0。在main
函数中,我们也使用new
运算符分配了幻方的动态数组。最后,记得在程序结束前使用delete
运算符释放动态数组所占用的内存。
请注意,使用动态数组需要手动管理内存,并确保适当地释放分配的内存,以避免内存泄漏。