本题目要求读入菱形起始字母和菱形的高度,然后输出空心字符菱形。所谓“空心菱形”是指:每行由两端为字母、中间为空格的字符串构成,每行的字符串中心对齐;上半部分相邻两行字符串长度差2,且字母从给定的起始字母逐一递增;下半部分与上半部分对称。
输入格式:
输入在一行中给出起始字母(范围为英文大写字母A-G)和菱形的高度(为不超过10的奇数)。
输出格式:
输出空心字符菱形。
输入样例:
B 5
输出样例:
B
C C
D D
C C
B
代码长度限制 16 KB
时间限制 400 ms
内存限制 64 MB
- 1.曼哈顿距离
- 2.样例分析
- 3.思路形成
- 4.判断字母
- 5.判断空格
- 6.完整答案
1.曼哈顿距离
在讲解本题之前,先引入本题用到的非常重要的数学知识——曼哈顿距离。曼哈顿距离是通过沿坐标轴的网格线移动来测量两点之间的距离,只能水平和垂直方向移动,而不能斜向移动。可以用数学公式表示为:
d = ∣ x 1 − x 2 ∣ + ∣ y 1 − y 2 ∣ d = ∣x_1 − x_2∣ + ∣y_1 − y_2∣ d=∣x1−x2∣+∣y1−y2∣
若在平面内存在两点(x1, y1)和(x2, y2),d即为两点的曼哈顿距离。
2.样例分析
以n = 5为例,通过上述引入的曼哈顿距离(以下简称距离d)可知,本题首先需要确认基点,其余点均可求出距离。因为菱形是高度对称的图形,我们不妨设中心点为距离的基点。距离如下图所示:
通过对比两图,我们不难发现出现字母的位置均为距离d为2的位置。因此我们可以猜测,出现字母的位置距离d唯一且相等。(多次改变n的值,得到的结果均是如此)
3.思路形成
因为n = 5,而距离d又是2,可以猜测n与距离d的关系
int d = (n + 1) / 2 - 1;
因为距离d是横纵坐标之间的距离,我们不妨将此菱形放在直角坐标系中,左上角的坐标为(1, 1)
基点位于菱形中心,所以坐标为(3, 3),因此可以通过n值表示基点坐标:
int cx = (n + 1) / 2;
int cy = (n + 1) / 2;
确定基点坐标后,可以通过嵌套循环来遍历每个位置,将循环中的变量当做每个位置x,y的值。
for (int i = 1; i <= n; i ++)
{
for (int j = 1; j <= n; j ++)
{
}
}
4.判断字母
出现字母处的情况比较简单,因此先判断出现字母的位置,由上述分析可知,当距离等于d时出现字母
if (abs(i - cx) + abs(j - cy) == d)
printf("%c", a);
由题意可知上半段字母递增,下半段字母递减。因此还需额外进行判断:
n = 5时,前3行递增(注意只增了两次),可得行数与n的关系
if (i < (n + 1) / 2) //此处不能有等号
a += 1;
else
a -= 1;
5.判断空格
判断空格较为复杂,因为只有左半边外侧出现了空格。下面列举一种典型的错误写法:
if (abs(i - cx) + abs(j - cy) != d)
printf(" ");
该写法判断时忽略了左右区别,会导致右半边也出现空格。
空格在小于字母距离d的位置一定会出现,因此可以先考虑这种简单情况
if (abs(i - cx) + abs(j - cy) < d)
printf(" ");
想要让左侧出现空格而右侧没有,就要对横坐标 j 进行限制,当 j <= (n + 1) / 2 即可表示左半边。因此:
if (abs(i - cx) + abs(j - cy) > d && j <= (n + 1) / 2)
printf(" ");
合并可写为:
if (abs(i - cx) + abs(j - cy) > d && j <= (n + 1) / 2 || abs(i - cx) + abs(j - cy) < d)
printf(" ");
6.完整答案
#include <stdio.h>
#include <math.h>
int main()
{
int n;
char a;
scanf("\n%c%d", &a, &n);
int d = (n + 1) / 2 - 1;
int cx = (n + 1) / 2, cy = (n + 1) / 2;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
if (abs(i - cx) + abs(j - cy) == d)
printf("%c", a);
if (abs(i - cx) + abs(j - cy) > d && j <= (n + 1) / 2 || abs(i - cx) + abs(j - cy) < d)
printf(" ");
}
if (i < (n + 1) / 2)
a += 1;
else
a -= 1;
printf("\n");
}
return 0;
}