当前位置:首页题目 > 正文

NOIP基础算法(C++)-模拟算法例题3-神奇的幻方

作者:野牛程序员:2023-07-03 20:04:43题目阅读 3297

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。

接下来,我们使用两个变量rowcol来追踪当前要填充的位置。我们将数字1放在第一行的中间位置,即row = 0col = 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运算符释放动态数组所占用的内存。

请注意,使用动态数组需要手动管理内存,并确保适当地释放分配的内存,以避免内存泄漏。


野牛程序员教少儿编程与信息学奥赛-微信|电话:15892516892
野牛程序员教少儿编程与信息学竞赛-微信|电话:15892516892
相关推荐

最新推荐

热门点击