题目
英文原题请看https://onlinejudge.org/external/1/177.pdf。
中文题请看https://www.luogu.com.cn/problem/UVA177。
分析
首先,我们可以从起点开始,模拟出一条路,用一个字符串记录,R代表向左移,U代表向上移,L代表向上移,D代表向下移。比如_|是RU。
我们列举几个字符串找规律。
N=1 | S="RU" | _| |
N=2 | S="RULU" | |_ _| |
N=3 | S="RULULDLU" | _ |_| |_ _| |
N=4 | S="RULULDLULDRDLDLU" | _ _ |_|_| |_ _| _| |_| |
从N=2开始,把S分成两半,前一半和上一个S是完全相同的,再把S的后半部分成两半,也把上一个S分成两半,后半部分的前半部分和上一个S的前半部分相反,后半部分的后一半和上一个S的后半部分相同。这样,要求出第N次折后的S递推一下就可以了。可以参考一下c++代码。
string move="RU";
for(int i=1;i<N;i++){
string next="";
next+=move;
for(int i=0;i<move.size()/2;i++){
if(move[i]=='R'||move[i]=='L') next+=move[i]^'R'^'L';
else next+=move[i]^'U'^'D';
}
next+=move.substr(move.size()/2);
move=next;
}
现在可以按照路径“走”了。假设起点在(0, 0),依次判断往上、下、左、右的情况。可是坐标中会出现负数,所以要把所有x坐标加上同样的数使得所有x为非负整数,y坐标也是一样。最后把答案记录下来。下面是参考代码。
int max_r=-INF,max_c=-INF,min_r=INF,min_c=INF,x=0,y=0;
max_c=max(max_c,y);
min_c=min(min_c,y);
max_r=max(max_r,x);
min_r=min(min_r,x);
vector<pair<int,int> > place;
place.push_back(make_pair(0,0));
for(int i=1;i<move.size();i++){
if(move[i]=='D'){
if(move[i-1]=='R'){
x++;
y++;
}
else if(move[i-1]=='L'){
x++;
y--;
}
else x++;
}
if(move[i]=='U'){
if(move[i-1]=='R') y++;
else if(move[i-1]=='L') y--;
else x--;
}
if(move[i]=='R'){
if(move[i-1]=='U'){
x--;
y++;
}
else y++;
}
if(move[i]=='L'){
if(move[i-1]=='U'){
x--;
y--;
}
else y--;
}
place.push_back(make_pair(x,y));
max_c=max(max_c,y);
min_c=min(min_c,y);
max_r=max(max_r,x);
min_r=min(min_r,x);
}
max_c-=min_c;
max_r-=min_r;
for(int i=0;i<=max_r;i++) for(int j=0;j<=max_c;j++) ans[i][j]=' ';
for(int i=0;i<place.size();i++){
place[i].first-=min_r;
place[i].second-=min_c;
}
for(int i=0;i<place.size();i++){
if(move[i]=='U'||move[i]=='D') ans[place[i].first][place[i].second]='|';
else ans[place[i].first][place[i].second]='_';
}
输出记得不能有多余空格哦!
参考代码
#include <bits/stdc++.h>
#define INF 1000000000
using namespace std;
int N;
char ans[20000][20000];
void solve(){
cin>>N;
if(N==0) exit(0);
string move="RU";
for(int i=1;i<N;i++){
string next="";
next+=move;
for(int i=0;i<move.size()/2;i++){
if(move[i]=='R'||move[i]=='L') next+=move[i]^'R'^'L';
else next+=move[i]^'U'^'D';
}
next+=move.substr(move.size()/2);
move=next;
}
int max_r=-INF,max_c=-INF,min_r=INF,min_c=INF,x=0,y=0;
max_c=max(max_c,y);
min_c=min(min_c,y);
max_r=max(max_r,x);
min_r=min(min_r,x);
vector<pair<int,int> > place;
place.push_back(make_pair(0,0));
for(int i=1;i<move.size();i++){
if(move[i]=='D'){
if(move[i-1]=='R'){
x++;
y++;
}
else if(move[i-1]=='L'){
x++;
y--;
}
else x++;
}
if(move[i]=='U'){
if(move[i-1]=='R') y++;
else if(move[i-1]=='L') y--;
else x--;
}
if(move[i]=='R'){
if(move[i-1]=='U'){
x--;
y++;
}
else y++;
}
if(move[i]=='L'){
if(move[i-1]=='U'){
x--;
y--;
}
else y--;
}
place.push_back(make_pair(x,y));
max_c=max(max_c,y);
min_c=min(min_c,y);
max_r=max(max_r,x);
min_r=min(min_r,x);
}
max_c-=min_c;
max_r-=min_r;
for(int i=0;i<=max_r;i++) for(int j=0;j<=max_c;j++) ans[i][j]=' ';
for(int i=0;i<place.size();i++){
place[i].first-=min_r;
place[i].second-=min_c;
}
for(int i=0;i<place.size();i++){
if(move[i]=='U'||move[i]=='D') ans[place[i].first][place[i].second]='|';
else ans[place[i].first][place[i].second]='_';
}
for(int i=0;i<=max_r;i++){
int curmxj=max_c;
while(ans[i][curmxj]==' ') curmxj--;
for(int j=0;j<=curmxj;j++) cout<<ans[i][j];
cout<<endl;
}
cout<<"^\n";
}
int main(){
while(1) solve();
}