打印十字图

问题描述
小明为某机构设计了一个十字型的徽标(并非红十字会啊),如下所示:

对方同时也需要在电脑dos窗口中以字符的形式输出该标志,并能任意控制层数。

输入格式
一个正整数 n (n<30) 表示要求打印图形的层数。

输出格式
对应包围层数的该标志。

样例输入1
1
样例输出1

样例输入2
3

样例输出2

提示
请仔细观察样例,尤其要注意句点的数量和输出位置。

——分割线之初入江湖——

分析:
这是一道典型的文字图形类题,其要求是能根据输入,打印出对应的图形
读完这道题,让我想起了当初学 C++,在学到 for 循环时的一个题目,如下:
题目

要求编程实现对于任何的输入n,程序都能根据上述的规则输出对应的图案
这道题现在看来很简单,但是在当时还是很懵的
我们来说说这道题的解题思路,显然这里存在一个规律:
对于每一行(假设为第i行(i从1开始),当前输入的值为n)
前面的空格数量都满足:空格数量=n- i
中间的 “ * ” 号数量满足: “ * ” 数量= 2 ╳ i - 1
于是可以很快的写出这道题的代码为:

void print(int n)
{for(int i=1;i<=n;i++){for(int j=1;j<=n-i;j++)cout<<” ”;for(int j=1;j<=2*i-1;j++)cout<<”*”;cout<<endl;}
}

这道题的特点是图形与其对应的序号有着简单的对应关系,这个对应关系简单到能够直接根据当前行数得出当前行所需要打印的图像,也就是说对该图像的每一行都存在着一个通用的公式。因此我们可以直接通过最多两层的循环将整个图像打印出来,并且不需要任何的提前处理就能直接输出。

——分割线之艰难磨砺——

反观本题,发现这里的图像复杂很多。为了能更直观地看清本题中的图像特征,下面我先将本题中的部分图像绘出(其中红色背景替代”$”,无背景替代”.”)。首先是n=1的图像:
n=1的“十字架”图案

然后是 n=2 的图像:

n=2的“十字架”图案

可以很明显地发现,本题中的图像不具备像上面那道题一样简单的对应关系(存在对每行都通用的公式),也不具备直接输出的条件。且对于每个图像而言,当n增加1时,其就会在最外层再多增加一层“十字架”。而这样的动态变化模式也导致了对于整个图像中的每一行而言,其并不存在一个通用的公式。这样的下场是,我们必须用一个二维数组来将整个图像的特征保存(当然,这里面可能有多道步骤),最终再通过这个点阵数组将整个图像打印出(比如说在数组中用1表示某个点为”$”,用0表示某个点为”.”)。

①首先我们来观察每个图中最中间的那个“十字架”的位置,如下图所示(蓝色部分):

中间部分的“十字架”
可以发现,无论n取值多少,最中间的那个“十字架”都在图层的最中央,且长度为5,于是可以得到最中间的这个“十字架”的位置为:(N/2+1,N/2+1)
注:假设当前图像的规格为N ╳ N,且存储在二维数组中的横纵坐标均从1开始,下同
进而可以通过一重循环将整个最中间的“十字架”位置标记出:

for(int i=N/2-1;i<=N/2+3;i++)map[N/2+1][i]=map[i][N/2+1]=1;      //一横一竖

②接下来观察外围“十字架”在其四个边角部位的位置,如下图所示(蓝色部分):

"十字架"的边角部分
由于外围的“十字架”有多层,故我在这里规定“十字架”的层数从最外层到最里层,层数分别为1,2,……,n
若假设当前“十字架”为第 i 层,则可以得到第i层“十字架”的四个边角坐标与i和N存在以下关系:
1.左上部分的边角(格点1)坐标为(x,y),其中x=2 ╳ i+1,y=2 ╳ i+1
则格点1上方格子的坐标为:(x-1,y)、格点1左边格子的坐标为:(x,y-1)
2.右上部分的边角(格点2)坐标为(x,y),其中x=2 ╳ i+1,y=N- 2 ╳ i
则格点2上方格子的坐标为:(x-1,y)、格点2右边格子的坐标为:(x,y+1)
3.右下部分的边角(格点3)坐标为(x,y),其中x=N- 2 ╳ i,y=N- 2 ╳ i
则格点3下方格子的坐标为:(x+1,y)、格点3右边格子的坐标为:(x,y+1)
4.右上部分的边角(格点4)坐标为(x,y),其中x=N- 2 ╳ i,y=2 ╳ i+1
则格点4下方格子的坐标为:(x+1,y)、格点4左边格子的坐标为:(x,y-1)
于是可以通过一层循环就实现这四个边角位置的标记,如下:

for(int i=1;i<=n;i++)
{int x=2*i+1,y=2*i+1;//左上边角map[x][y]=map[x][y-1]=map[x-1][y]=1; //右上边角y=N-2*i;map[x][y]=map[x][y+1]=map[x-1][y]=1;//右下边角x=N-2*i;map[x][y]=map[x][y+1]=map[x+1][y]=1;//左下边角y=2*i+1;map[x][y]=map[x][y-1]=map[x+1][y]=1;
}

③接下来观察外围“十字架”在其“四个墙壁”的位置,如下图所示(蓝色部分):

"十字架"的“四个墙壁”
这里同样规定“十字架”的层数从最外层到最里层,层数分别为1,2,……,n;图像规格为N ╳ N
可以发现,其实这“四个墙壁”和第②部分中的四个边角部分具有几乎等同的规则。首先可以看出的是,这四条边的长度都是一致的;其次这些边的长度都等于整个图像的总长(N)减去前后各两个格子的长度(当然,随着“十字架”由最外层逐渐往内层移动时,其减去的前后的格子也在逐渐增加)。则为了能把中间的这些格子的位置标记出,我们就需要对这些位置的起始坐标进行统计(循环赋值需要起始两个边界值)。
1.首先来看最外层“十字架”的最上方“墙壁”(图中蓝色部分)的起始坐标:
行数:第一层“十字架”的行数显然为1,而第二层行数变为了3,第三层则变成了5,于是可以得到“十字架”上方“墙壁”的行数随“十字架”层数的增加,其变化规律为:2 ╳ i - 1(i为当前“十字架”的层数)。当然,对于“十字架”上方“墙壁”而言,其行数是固定的,列数是变化的;
列数:通过上图的规律,可以直接给出列数的起点坐标为:2 ╳ i+1;终点坐标为N - 2 ╳ i
则可以给出对“十字架”上方“墙壁”的位置进行标记的代码为:

for(int i=1;i<=n;i++)             //“十字架”层数的增加for(int j=2*i+1;j<=N-2*i;j++)   //上方“墙壁”列数的增加map[2*i-1][j]=1;

2.现在来看“十字架”的右侧“墙壁”的起始坐标(显然此时行数是变化的,而列数是固定的):
行数:可以直接给出行数的起点坐标也为:2 ╳ i +1;终点坐标也为N-2 ╳ i
列数:第一层“十字架”的列数显然为N,而第二层行数变为了N - 2,第三层则变成了N - 4,于是可以得到“十字架”右侧“墙壁”的列数随“十字架”层数的增加,其变化规律为:N-2 ╳ ( i - 1)
则可以给出对“十字架”右侧“墙壁”的位置进行标记的代码为:

for(int i=1;i<=n;i++)             //“十字架”层数的增加for(int j=2*i+1;j<=N-2*i;j++)   //右侧“墙壁”行数的增加map[j][N-2*(i-1)]=1;

3.再看“十字架”的下方“墙壁”的起始坐标(此时行数是固定的,而列数是变化的):
行数:第一层“十字架”的列数显然为N,而第二层行数变为了N-2,第三层则变成了N-4,于是可以得到“十字架”右侧“墙壁”的列数随“十字架”层数的增加,其变化规律为:N-2 ╳ ( i - 1)
列数:可以直接给出列数的起点坐标为:2 ╳ i+1;终点坐标为N-2 ╳ i
则可以给出对“十字架”下方“墙壁”的位置进行标记的代码为:

for(int i=1;i<=n;i++)             //“十字架”层数的增加for(int j=2*i+1;j<=N-2*i;j++)   //下方“墙壁”列数的增加map[N-2*(i-1)][j]=1;

4.最后看“十字架”的左侧“墙壁”的起始坐标(此时行数是变化的,而列数是固定的):
行数:可以直接给出行数的起点坐标也为:2 ╳ i+1;终点坐标也为N - 2 ╳ i
列数:第一层“十字架”的列数显然为1,而第二层行数变为了3,第三层则变成了5,于是可以得到“十字架”左侧“墙壁”的列数随“十字架”层数的增加,其变化规律为:2 ╳ i - 1
则可以给出对“十字架”左侧“墙壁”的位置进行标记的代码为:

for(int i=1;i<=n;i++)             //“十字架”层数的增加for(int j=2*i+1;j<=N-2*i;j++)   //左侧“墙壁”行数的增加map[j][2*i-1]=1;

其实不难发现在上述4点中,行和列的变化用代码表示时,其外层条件均一致
于是我们可以把这所有的行列变化都放在一个循环体之下,如下:

for(int i=1;i<=n;i++)for(int j=2*i+1;j<=N-2*i;j++)map[2*i-1][j]=map[j][N-2*(i-1)]=map[N-2*(i-1)][j]=map[j][2*i-1]=true;

至此,整个图像的点阵特征均被放进了一个二维数组中
我们可以直接通过事先设定好的约定(1替代”$”,0替代”.”)来遍历整个二维数组,从而将整个图像打印出,代码如下:

for(int i=1;i<=N;i++)
{for(int j=1;j<=N;j++)if(map[i][j]) cout<<"$";else cout<<".";cout<<endl;
}

——分割线之炉火纯青——

下面直接给出本题的完整代码:

#include<iostream>
using namespace std;const int MAX=130; //需设置为大于5+4*30的数
bool map[MAX][MAX]; void print(int n)
{//通过n计算出打印十字图的规格(N*N)int N=5+4*n; //首先标记最内层的十字架for(int i=N/2-1;i<=N/2+3;i++)map[N/2+1][i]=map[i][N/2+1]=true;  //一横一竖//然后从最外层到里层逐个标记十字架for(int i=1;i<=n;i++){//接下来标记四个边角部分int x=2*i+1,y=2*i+1;//左上边角map[x][y]=map[x][y-1]=map[x-1][y]=true; //右上边角y=N-2*i;map[x][y]=map[x][y+1]=map[x-1][y]=true;//右下边角x=N-2*i;map[x][y]=map[x][y+1]=map[x+1][y]=true;//左下边角y=2*i+1;map[x][y]=map[x][y-1]=map[x+1][y]=true;//接下来标记十字架的非边角部位(即“四个墙壁”)for(int j=2*i+1;j<=N-2*i;j++)map[2*i-1][j]=map[j][N-2*(i-1)]=map[N-2*(i-1)][j]=map[j][2*i-1]=true; } //打印for(int i=1;i<=N;i++){for(int j=1;j<=N;j++)if(map[i][j]) cout<<"$";else cout<<".";cout<<endl;}
}int main()
{int n;cin>>n;print(n);return 0;
}

13省Cc8-打印十字图(小明为某机构设计了一个十字型的徽标(并非红十字会啊),如下所示)相关推荐

  1. java 打印十字图

    打印十字图 小明为某机构设计了一个十字型的徽标(并非红十字会啊),如下所示(可参见p1.jpg)  对方同时也需要在电脑dos窗口中以字符的形式输出该标志,并能任意控制层数. 为了能准确比对空白的数量 ...

  2. 【每日蓝桥】8、一三年省赛Java组真题“打印十字图”

    你好呀,我是灰小猿,一个超会写bug的程序猿! 欢迎大家关注我的专栏"每日蓝桥",该专栏的主要作用是和大家分享近几年蓝桥杯省赛及决赛等真题,解析其中存在的算法思想.数据结构等内容, ...

  3. 历届试题 打印十字图(模拟)

    试题 历届试题 打印十字图 资源限制 时间限制:1.0s 内存限制:256.0MB $Daily English: 我想要提醒这个星球上的人类唯一的一件事就是:我们 依赖地球母亲生存. The onl ...

  4. 蓝桥杯-c语言 打印十字图

    打印十字图 题目描述: 问题描述小明为某机构设计了一个十字型的徽标(并非红十字会啊),如下所示:..$$$$$$$$$$$$$.. ..$...........$.. $$$.$$$$$$$$$.$$ ...

  5. 历届试题-打印十字图(打印)

    题目详情 问题描述 小明为某机构设计了一个十字型的徽标(并非红十字会啊),如下所示:..$$$$$$$$$$$$$.. ..$...........$.. $$$.$$$$$$$$$.$$$ $... ...

  6. 历届试题 打印十字图

    问题描述 小明为某机构设计了一个十字型的徽标(并非红十字会啊),如下所示: 对方同时也需要在电脑dos窗口中以字符的形式输出该标志,并能任意控制层数. 输入格式 一个正整数 n (n<30) 表 ...

  7. 蓝桥杯 历届试题 打印十字图

    问题描述 小明为某机构设计了一个十字型的徽标(并非红十字会啊),如下所示: 对方同时也需要在电脑dos窗口中以字符的形式输出该标志,并能任意控制层数. 输入格式 一个正整数 n (n<30) 表 ...

  8. 打印十字图-Java

    题目描述: 小明为某机构设计了一个十字型的徽标(并非红十字会啊),如下所示:..$$$$$$$$$$$$$.. ..$...........$.. $$$.$$$$$$$$$.$$$ $...$... ...

  9. 蓝桥杯—打印十字图—Java

    1.问题描述 小明为某机构设计了一个十字型的徽标(并非红十字会啊),如下所示(可参见p1.jpg)     对方同时也需要在电脑dos窗口中以字符的形式输出该标志,并能任意控制层数. 为了能准确比对空 ...

最新文章

  1. java类的基本组成和使用,Java架构师成长路线
  2. 【upc5020】 Knight
  3. unity3d显示c4d材质_C4D小白最常踩的9个坑,看看你中招了没?
  4. c语言三个数从小到大排序/输出_C语言经典100题(6)
  5. gitlab的用户使用手册
  6. FreeBSD的起源和发展
  7. 二叉树C++ | 广度优先遍历(层级顺序遍历)_2
  8. 微服务和数据库到底是什么关系?
  9. ElasticSearch 2 (18) - 深入搜索系列之控制相关度
  10. Vue3 非常好用的中文文档以及一份 Vue 3 新文档学习笔记
  11. visio软件接口流程图_绘制流程图——Visio可以让你事半功倍哦!
  12. 电源 PFC(功率因数校正)电路拓扑,共计100多份,内含A PFC,连续断续,交错,维也纳,各功率段的PFC电路,还有电感 设计选型
  13. CSS中absolute和relative
  14. java史上最全面试题(转载于骆昊)
  15. nvidia所有版本显卡驱动下载地址
  16. 星星之火-5:数字无线通信相对模拟无线通信的优点
  17. 智能制造的实现,少不了APS排产系统
  18. c++练习题,动物爱吃什么
  19. 给大家排个雷,ensp中nat不成功原因
  20. 数组名 int a[5] = {1,2,3,4,5}; int *ptr = (int *)( a + 1);

热门文章

  1. AVL树(C语言实现)
  2. 如何拯救你的职业困境?
  3. 23岁我写了第一封情书
  4. SPGridView 研究笔记 Part 1 - 基础和项菜单
  5. 礼品平台网站对于商家有什么用处
  6. 人工智能,丹青圣手,全平台(原生/Docker)构建Stable-Diffusion-Webui的AI绘画库教程(Python3.10/Pytorch1.13.0)
  7. WPF控件置顶及置底功能
  8. Android 中arm64-v8a、armeabi-v7a、armeabi、x86简介~
  9. 监控增加流媒体服务器的好处,视频监控服务器主要有哪些优势及特点
  10. 浅谈企业中台商业模式及建设思路