GESP2025年9月认证C++二级真题与解析(编程题2(菱形))

一、先看原题:


二、🎨 题目故事:小 A 要画一个菱形

1、🧸 题目故事化

小 A 学会了编程,他想用代码来画画 🖌️

这次,他要画一个 # 组成的菱形

  • 画布是一个 n × n 的方格

  • n 是一个 大于 1 的奇数

  • 不画 # 的地方,用 . 填充


2、📌 举个例子

n = 5 时,要画成这样:

cpp 复制代码
..#..
.#.#.
#...#
.#.#.
..#..

是不是像一颗 💎 钻石?


三、🧠 这道题真正想考什么?

很多同学一看到这个图形题就慌了,其实这道题只考 3 个点:

考点 说明
双重 for 循环 一行一行画
行号 i、列号 j 找当前位置
找"哪些点该画 #" 核心逻辑

👉 最难的不是写代码,而是:判断什么时候输出 #


四、🧩 一步一步想:什么时候该画 #


1、方法一 ⭐⭐⭐⭐

👉 发现"曼哈顿距离相等"的高明方法

这是 GESP 二级最推荐的思路

也是 从"画画"走向"数学建模" 的关键一步


1️⃣ 先讲故事

🧸 想象你站在操场正中间 🏟️

你问一个问题:

哪些格子,刚好在"菱形边界"上?

答案是:

👉 到中心点的"上下走的步数 + 左右走的步数"一样多

这就叫:

🎯 曼哈顿距离


2️⃣ 什么是"曼哈顿距离"?

在棋盘上:

  • 只能 上下左右走

  • 不能斜着飞 ✈️

那么:

cpp 复制代码
距离 = |行差| + |列差|

3️⃣ 用菱形来理解

设:

  • n = 5

  • 中心在 (3, 3)

  • k = n / 2 = 2

那么:

💎 所有在菱形边上的点,都满足:

cpp 复制代码
|当前行 - 中心行| + |当前列 - 中心列| == 2

4️⃣ 举几个"一眼就懂"的例子

✅ 在菱形上

  • (1,3)

    |1−3| + |3−3| = 2 ✔

  • (3,1)

    |3−3| + |1−3| = 2 ✔

❌ 不在菱形上

  • (1,1)

    |1−3| + |1−3| = 4 ✘


5️⃣ 对应到代码(核心只有一行)

cpp 复制代码
if (abs(i - center) + abs(j - center) == k)
    '#'
else
    '.'

完整程序:

cpp 复制代码
#include <algorithm>
#include <cstdio>
using namespace std;
int main() {
    int n, i, j, k;
    scanf("%d", &n);
    k = n / 2;                           //计算半径
    for (i = 1; i <= n; i++) {           //枚举点的行坐标
        for (j = 1; j <= n; j++) {       //枚举点的列坐标
            if (abs(k - i + 1) + abs(k - j + 1) == k)//计算曼哈顿距离
                printf("#");
            else
                printf(".");
        }
        printf("\n");                    //一行结束,转行
    }
    return 0;
}

方法二 ⭐⭐ 没有发现刚才高明的办法怎么办?

1、👉 把菱形当成"4 条斜线"的朴素方法

这是 没有发现距离规律时
非常自然、非常理性的思路


1️⃣ 先讲故事

🧸 同学看到这个菱形,会怎么想?

"它不就是

左上 → 右上 → 右下 → 左下

四条斜线拼起来的吗?"

完全正确 👍


2️⃣ 把菱形拆成 4 条边

假设 n = 5,中心是 (3,3)

四条边是:

1️⃣ 左上 ↗ 中心

2️⃣ 中心 ↘ 右上

3️⃣ 右下 ↙ 中心

4️⃣ 中心 ↖左下


3️⃣ 用数组"先画好,再统一输出"

解题思路

  • 先把整个 n × n 画布填成 全部都是 ' . '

  • 再分别画 左上、右上、右下、左下 四条边

  • 最后统一输出整个二维数组


2、分步画法:

1️⃣ 第一步:准备画布

cpp 复制代码
char g[100][100];

先全部填成 ' . ' :

cpp 复制代码
for (i)
  for (j)
    g[i][j] = '.';

2️⃣ 第二步:一条一条画斜线

举例:画"左上 → 中心"

cpp 复制代码
int x = center, y = 1;
for (int step = 0; step <= k; step++) {
    g[x][y] = '#';
    x--;
    y++;
}

其余三条边完全类似

行变化 列变化
左上 → 中 -1 +1
中 → 右上 +1 +1
右下 → 中 +1 -1
中 → 左下 -1 -1

3️⃣ 最后统一输出整个数组

cpp 复制代码
for (i)
  for (j)
    cout << g[i][j];

参考程序:

cpp 复制代码
#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;                 // 输入 n(奇数)

    // 画布,稍微开大一点
    char g[105][105];

    // 1、初始化:全部填成 '.'
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            g[i][j] = '.';
        }
    }

    int center = (n + 1) / 2; // 中心点坐标
    int k = n / 2;            // 半径

    // 2、 左上 -> 上中
    int x = center, y = 1;
    for (int step = 0; step <= k; step++) {
        g[x][y] = '#';
        x--;
        y++;
    }

    // 3、上中 -> 右上
    x = 1; 
    y = center;
    for (int step = 0; step <= k; step++) {
        g[x][y] = '#';
        x++;
        y++;
    }

    // 4、 右上 -> 下中
    x = center; 
    y = n;
    for (int step = 0; step <= k; step++) {
        g[x][y] = '#';
        x++;
        y--;
    }

    // 5、 下中 -> 左下
    x = n; 
    y = center;
    for (int step = 0; step <= k; step++) {
        g[x][y] = '#';
        x--;
        y--;
    }

    // 6、  输出整个画布
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            cout << g[i][j];
        }
        cout << '\n';
    }

    return 0;
}

3、 这种朴素画图方法的特点

✅ 优点:

  • 非常直观

  • 像"真的在画画"

  • 小学生很容易想到

❌ 缺点:

  • 情况多

  • 代码长

  • 容易写错边界


五、两种方法的对比

对比项 方法一:曼哈顿距离 方法二:四条斜线
思维层次 ⭐⭐⭐⭐ ⭐⭐
是否发现规律
代码长度
出错概率
适合比赛 非常适合 适合

六、考试建议

1、👶找不到规律就用最笨的方法

👉 不怕麻烦,一条一条的写

  • 建立空间感

  • 理解"行、列"的变化


2、🧠 能发现规律的同学

👉 找到方法(曼哈顿距离相等)

  • 从画图形 → 数学判断

  • 思维直接" 升级一档 "


3、📌 考试时间有限,那个是自己能想通的,就用那个,不要等。


相关推荐
君义_noip2 小时前
信息学奥赛一本通 1528:【例 2】单词游戏
c++·算法·信息学奥赛·一本通·csp-s
FL16238631292 小时前
[C++][cmake]基于C++在windows上部署yolo26的目标检测onnx模型
c++·windows·目标检测
朔北之忘 Clancy2 小时前
第一章 顺序结构程序设计(1)
c++·算法·青少年编程·竞赛·教材·考级·讲义
星火开发设计3 小时前
变量与常量:C++ 中 const 关键字的正确使用姿势
开发语言·c++·学习·const·知识
hetao17338373 小时前
2026-01-14~15 hetao1733837 的刷题笔记
c++·笔记·算法
a***59263 小时前
C++跨平台开发:挑战与解决方案
开发语言·c++
hetao17338373 小时前
2026-01-12~01-13 hetao1733837 的刷题笔记
c++·笔记·算法
Yu_Lijing3 小时前
基于C++的《Head First设计模式》笔记——外观模式
c++·笔记·设计模式
CoderCodingNo3 小时前
【GESP】C++六级考试大纲知识点梳理, (5) 动态规划与背包问题
开发语言·c++·动态规划