一开始看这题感觉无从下手,甚至一开始根本没理解题意 。后来明白了,是一张纸,每次都是从右向左折叠,注意折叠后不要动 。
折叠完n次后,最底下那一个纸条要保持原位置不动(水平放置),其他的按题目要求展开,从侧面就会看到一条连续的“美丽”曲线 。
那么怎么样找到这条曲线呢? 其实是有规律可循的 。我们把边看作路径,那么行走的方向命令就可以写出了 。 如下:
n = 1 --> ru
n = 2 --> rulu
n = 3 --> rululdlu
n = 4 --> rululdluldrdldlu
其中udlr分别是上下左右 。
发现规律了吧? 没错,每一次都会增加一倍的步数,而且对于增加的那部分,前一半和上一次的相反,后一半相同 。
那么就不难写出了,当然绘制图像还是有点麻烦的,不过我们可以事先将数组开大一点,取中间的一个点为起始点进行绘图 。 当然,需要注意每一行的最大列都需要记录,不然会多输出很多空格,导致WA
细节参见代码:
#include<bits/stdc++.h>
using namespace std;
int n;
char s[50000][2000]; //开一个足够大的图像
int main() {
while(~scanf("%d",&n)&&n) {
memset(s,0,sizeof(s));
int cnt = 1;
char buf[50000];//行走命令
buf[1] = 'r'; buf[2] = 'u'; buf[3] = '\0';
while(cnt<n) { // 记录行走方向命令
int len = strlen(buf+1);
for(int i=1;i<=len;i++) {
if(i<=len/2) {
if(buf[i] == 'l') buf[i+len] = 'r';
else if(buf[i] == 'r') buf[i+len] = 'l';
else if(buf[i] == 'u') buf[i+len] = 'd';
else buf[i+len] = 'u';
}
else buf[i+len] = buf[i];
}
cnt++; buf[len*2+1] = '\0';
}
int min_r = 25000,max_r = 25000,min_c,max_c[50000];//按照命令,绘制图像 。
for(int i=1;i<=25000;i++) { max_c[i] = -2000; }
int cur_r = 25000,cur_c = 1000; min_c = 1000; max_c[25000] = 1000;
int len = strlen(buf+1);
s[cur_r][cur_c] = '_';
for(int i=2;i<=len;i++) {
if(buf[i-1]=='r') {
if(buf[i]=='u') { cur_c++; s[cur_r][cur_c] = '|'; }
else if(buf[i]=='d') { cur_r++; cur_c++; s[cur_r][cur_c] = '|'; }
}
else if(buf[i-1]=='l') {
if(buf[i]=='u') { cur_c--; s[cur_r][cur_c] = '|'; }
else { cur_r++; cur_c--; s[cur_r][cur_c] = '|' ;}
}
else if(buf[i-1]=='u') {
if(buf[i]=='r') { cur_r--; cur_c++; s[cur_r][cur_c] = '_'; }
else { cur_r--; cur_c--; s[cur_r][cur_c] = '_'; }
}
else {
if(buf[i]=='r') { cur_c++; s[cur_r][cur_c] = '_'; }
else { cur_c--; s[cur_r][cur_c] = '_'; }
}
min_r = min(min_r,cur_r); max_r = max(max_r,cur_r);
min_c = min(min_c,cur_c); max_c[cur_r] = max(max_c[cur_r] ,cur_c);
} //打印图像,注意每一行的最大列都要记录,否则多输出的空格会导致WA
for(int i=min_r;i<=max_r;i++) {
for(int j=min_c;j<=max_c[i];j++) {
if(s[i][j] == 0) printf(" ");
else printf("%c",s[i][j]);
}
printf("\n");
}
printf("^\n");
}
return 0;
}