UVA 177题解

题目

英文原题请看https://onlinejudge.org/external/1/177.pdf

中文题请看https://www.luogu.com.cn/problem/UVA177

分析

首先,我们可以从起点开始,模拟出一条路,用一个字符串记录,R代表向左移,U代表向上移,L代表向上移,D代表向下移。比如_|是RU。

我们列举几个字符串找规律。

N=1S="RU"_|
N=2S="RULU"

|_

_|

N=3S="RULULDLU"   _
|_| |_
     _|
N=4S="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();
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值