问题描述
小A很喜欢十字架,并喜欢用各种方式产生十字架的样子。小A不满足简单的十字架输出效果,所以重新定义了一种高大上的十字架输出方式。
给一个n(1≤n≤10) , 输出对应的图形,具体形式如下:
1.当n=1的时候,输出一个小写字母"o" :
o
2.当n≥2的时候,复制n=n-1时候的图像,并且在n-1图像的上、下、左、右都粘贴一个一模一样的图形。
如n=2时,在原图"o"的上下左右都粘贴一个"o",所以最后输出的是这样一个图形:
o
ooo
o
输入 | 输出 |
---|---|
包含多组数据,第一行是数据组数T(T≤10),随后有T行,每组数据占一行,其中包含一个数字n(1 ≤ n ≤ 10) 。 | 首先每行输出:“Case #x:”,x表示这是第几组数据,在随后的行中输出对应图形。注意每行输出字符数应该与o处于最右的那一行的字符数相同;如果对应位置没有字母o,就在那一个位置输出一个空格。 |
样例输入:2 2 3
样例输出:
解决策略
本题主要需要被解决的问题是如何复制上一级的图形,并且将这个图形在原图形的上下左右各粘贴一个,从而形成新的图形。
memset的用法
头文件:<string.h> 或 <memory.h>
memset(结构体/数组名 , 用于替换的ASCII码对应字符 , 前n个字符 );
memset(结构体/数组名 , "用于替换的字符“ , 前n个字符 );
在本例中将使用memset函数实现:将所有除了需要输出“o”的位置改为输出“(空格)”
#include<cstring>
memset(a," ",sizeof(a));
方法体的书写
首先可以写一个方法体,便于重复调用打印输出的那一部分代码
因为涉及到二维数组,所以可以先申请一个比较大的数组空间(题目中已经有了描述,n的值最大不能超过10)(不过这不是一个好的习惯)
经过对输出图形的观察,可以发现有如下的规律
n:输入的数据 ,m:原图形被复制后的中心与原图中心距离
n | m |
---|---|
1 | – |
2 | 1 |
3 | 3 |
4 | 9 |
5 | 27 |
… | … |
所以可以发现n和m的关系是m=3(n-2)的
当n=1时,仅仅打印输出一个"o",当n>1时,可以先确定各个复制后图形的中心位置,然后再复用打印部分的方法体,实现复制的工作
方法体代码如下:
#define N 1000
char a[N][N];
void print(int x,int y,int n) {
int m = pow(3, n - 2);
if (n == 1) {
a[x][y] = 'o';
}
else {
print(x, y, n - 1);
print(x - m, y, n - 1);
print(x + m, y, n - 1);
print(x, y - m, n - 1);
print(x, y + m, n - 1);
}
}
然后便是写出主方法了
在这里需要判断数组的中心坐标
b | x |
---|---|
1 | 1 |
2 | 2 |
3 | 5 |
4 | 14 |
5 | 41 |
… | … |
可以发现x=3(b-2) *3/2+1/2,亦即x=3(b-2) +(3(b-2) +1)/2.因此可以据此打印出各部分中心位置的图形,然后复用方法体便可完成问题的需求
主方法代码如下:
int main() {
int T,n;
cin >> T;
int c = T;
while (T--) {
cin >> n;
if (n > 10) {
return 0;
}
cout << "Case #" << c-T<< ":"<<endl;
memset(a, ' ', sizeof(a)); //重置数组中的元素,用空格替换
int x = pow(3, n - 2) + (pow(3, n - 2) + 1) / 2;
print(x, x, n);
int m = pow(3, n - 1);
for (int x = 1; x <=m; x++) {
for (int y = 1; y <=m; y++) {
cout << a[x][y];
}
cout << endl;
}
}
}