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、📌 考试时间有限,那个是自己能想通的,就用那个,不要等。


相关推荐
FlightYe11 小时前
视界原理之3D视频(四):裸眼、眼镜和头显
android·linux·c++·3d·ffmpeg·音视频
by2099912 小时前
C++ 智能指针的所有权与使用
开发语言·c++·经验分享
Rover Ramble12 小时前
C++ 用互斥锁实现读写锁
开发语言·c++
你怎么知道我是队长12 小时前
C++零基础入门第2周:数据类型、运算符与表达式完全指南(附20段可运行代码+避坑清单)
c++
say_fall13 小时前
【Linux系统编程】Ext 文件系统:磁盘与存储、文件与目录、现代计算机究竟如何寻找文件
linux·运维·服务器·数据库·c++
雪落漂泊13 小时前
C++算法 滑动窗口篇(下)
开发语言·c++
你怎么知道我是队长16 小时前
C++零基础第3周:if/else、switch、for/while/do-while 控制流完全指南(附20段可运行代码+避坑清单)
java·开发语言·c++
青少儿编程课堂17 小时前
蓝桥杯·全国青少年信息素养大赛·电子学会Python/C++考级:倍增法求最近公共祖先LCA解析
c++·python·算法·bfs·信息学竞赛
雷✘17 小时前
C++ 类与对象的初始化机制、成员访问边界与拷贝优化
java·网络·c++
努力实干18 小时前
简单工厂模式(Simple Factory Pattern)——C++
开发语言·c++·简单工厂模式