题目链接在此。
题意理解
将给定的字符串按照U形进行输出。其中n1为左侧竖线包含的字符数,n2位底部包含的字符数,n3位右侧竖线包含的字符数,n1,n2,n3都包含拐角处的字符,于是有n1+n2+n3-2=N。此外,n1,n2,n3还需要满足以下条件:
1. n1==n3
2. n2 >= n1
3. 在满足以上条件的前提下,n1尽可能大
思路
对于“图形输出”的题型,一般都是两种方法:
1. 找到规律,直接输出
2. 找到规律,填入数组,输出数组
对于这个题,我第一次想到的是填数组的方法,详细介绍一下这个方法,至于直接输出的方法,只需要注意输出字符和空格的时机即可。
通过“题意理解”,我们可以列出几个式子:
n1<=n2
n3<=n2
n1+n2+n3-2 = N
这样一来,我们可以得到n2>=(N+3)/2,那么,当n1=n3=(N+3)/2
时是符合题意的,故n2=N-n1-n3+2。(具体过程读者自行演算、理解)
接下来就是将U分成左-下-右三个部分,填入print数组,细节不表,看代码即可。
这里需要注意:print数组需要初始化为全空格、print数组的大小如果是固定大小,至少需要[28][28](根据式子且N<80可推出)。
填入数组法代码
#include<stdio.h>
#include<string.h>
int main(){
char str[81];
int index = 0;
scanf("%s",str);
int n = strlen(str);
int n1,n2,n3;
n1 = n3 = (n+2)/3;
n2 = n-n1-n3+2;
char print[n1][n2];
//初始化print数组
for(int i = 0 ;i < n1; i++){
for(int j = 0; j < n2; j++){
print[i][j] = ' ';
}
}
//填充n1
for(int i = 0; i < n1; i++){
print[i][0] = str[index++];
}
index--;
//填充n2
for(int i = 0; i < n2; i++){
print[n1-1][i] = str[index++];
}
index--;
//填充n3
for(int i = n3-1 ; i >= 0; i--){
print[i][n2-1] = str[index++];
}
//输出print数组
for(int i = 0 ; i < n1; i++){
for(int j = 0; j < n2; j++){
printf("%c",print[i][j]);
}
printf("\n");
}
return 0;
}
直接输出法代码
不详细介绍,仍然需要通过上面的三个式子计算出n1,n2,n3的值,通过它们的值控制输出的行和列,以及每行的输出情况。
我的代码是用了left和right两个“指针”来控制输入字符串str[]数组的元素获取,也可以像《算法笔记》上通过N和循环变量的关系来得到需要输出的元素,皆可。
#include<stdio.h>
#include<string.h>
int main(){
char str[81];
scanf("%s",str);
int n1,n2,n3,n;
n = strlen(str);
n1 = n3 = (n+2)/3;
n2 = n-n1-n3+2;
int left = 0, right = n-1;
for(int i = 0 ; i < n1; i++){
for(int j = 0; j < n2; j++){
if( i < n1-1 ){ //输出n1和n3
if(j == 0){
printf("%c",str[left++]);
} else if( j == n2-1){
printf("%c",str[right--]);
}else{
printf(" ");
}
}else{
printf("%c",str[left++]);
}
}
printf("\n");
}
return 0;
}
我把输出控制(是输出符号还是输出空格)放到了循环变量里,也可以在每一行中,直接先输出左侧,然后输出中间,再输出右边,这样就不需要两个循环变量之间的关系了。(《算法笔记》是这种方式)