2024“钉耙编程”中国大学生算法设计超级联赛(6)1003 飞车狂飙

Problem Description

你现在正在筹备一场飞车比赛,众所周知,飞车比赛会同时有多辆车进行,因此赛道的设计十分关键。
现在你要修建由 n 个赛道段组成的赛道,赛道会被铺设在一个无限大的二维平面网格上,每个赛道段占一个单元格。
一条合法的赛道需要满足如下条件:

  • 赛道不能重叠,也就是相同的单元格上不能放置多个赛道段,因为重叠会使得赛车之间发生碰撞的概率提升。
  • 赛道必须成环,因为飞车比赛的起终点是在同一点。

你现在让一位工人在平面上某个单元格的一条边上就位,并按照你给的预命令来进行修建赛道。预命令是一个长度为 n 的仅包含 LRS 的字符串,其中 L 表示在他面向的单元格铺设一段相对于他面向的方向左转 90 度的赛道,R 表示在他面向的单元格铺设一段相对于他面向的方向右转 90 度的赛道,S 表示在他面向的单元格铺设一段相对于他面向的方向直行的赛道。之后,工人会顺着赛道来到下一条边上。
但你无法从你下达的预命令来看出赛道是否合法。现在你需要想办法判断它是否合法从而来指挥工人修建赛道。

Input

第一行一个整数 T(1≤T≤104),表示测试数据组数。

对于每组数据,第一行一个整数 n(1≤n≤105),表示轨道长度。第二行一个长为 n 且仅由 L,S,R 三种字符组成的字符串。
保证对于所有数据,满足 ∑n≤106。

Output

对于每组数据,输出一个整数表示该字符串对应的预命令是否合法。
如果轨道存在重叠,输出 −1;如果轨道无重叠,但不成环,输出 0;如果轨道无重叠且成环,输出 1。

Sample Input

4
1
S
4
RRRR
10
LSLSLSSLSL
18
LSSLSLSLSSSRSRSSRR

Sample Output

0

1

-1

Hint

样例中四条赛道如下图所示。其中蓝色线为初始时工人所在边,箭头朝向为初始时工人面向的方向。

思路:模拟题,定义一个向上的初始方向,将一个格子分成大小相同的四个正方形,定义起点是(0 , 0)点,只要判断途中一旦碰到重复的点,先判断满不满足环的条件,满足的话输出 1 ,不满足的话 输出 - 1 ,不然输出 0 。

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define pii pair<int,int>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
map<pii,int> mp;
signed main()
{
	IOS
	int t;
	cin >> t;
	while(t--){
		mp.clear();
		int n;
		cin >> n;
		string s;
		cin >> s;
		int x=0,y=0,dir=0,f=0,ff=0;
		mp[{0,0}]=0;
		for(int i=0;i<n;i++){
			if(s[i]=='S'){
				if(dir==0){
					y++;
					if(mp.count({x,y})) ff=1;
					mp[{x,y}]=dir;
					y++;
					if(mp.count({x,y})){
						if(i==n-1 && mp[{x,y}]==0 && x==0 && y==0) f=1;
						else ff=1;
					}else mp[{x,y}]=dir;
				}else if(dir==1){
					x++;
					if(mp.count({x,y})) ff=1;
					mp[{x,y}]=dir;
					x++;
					if(mp.count({x,y})){
						if(i==n-1 && mp[{x,y}]==0 && x==0 && y==0) f=1;
						else ff=1;
					}else mp[{x,y}]=dir;
				}else if(dir==2){
					y--;
					if(mp.count({x,y})) ff=1;
					mp[{x,y}]=dir;
					y--;
					if(mp.count({x,y})){
						if(i==n-1 && mp[{x,y}]==0 && x==0 && y==0) f=1;
						else ff=1;
					}else mp[{x,y}]=dir;
				}else{
					x--;
					if(mp.count({x,y})) ff=1;
					mp[{x,y}]=dir;
					x--;
					if(mp.count({x,y})){
						if(i==n-1 && mp[{x,y}]==0 && x==0 && y==0) f=1;
						else ff=1;
					}else mp[{x,y}]=dir;
				}
			}else if(s[i]=='L'){
				if(dir==0){
					y++;
					if(mp.count({x,y})) ff=1;
					mp[{x,y}]=dir;
					x--;
					if(mp.count({x,y})){
						if(i==n-1 && mp[{x,y}]==0 && x==0 && y==0) f=1;
						else ff=1;
					}else mp[{x,y}]=3,dir=3;
				}else if(dir==1){
					x++;
					if(mp.count({x,y})) ff=1;
					mp[{x,y}]=dir;
					y++;
					if(mp.count({x,y})){
						if(i==n-1 && mp[{x,y}]==0 && x==0 && y==0) f=1;
						else ff=1;
					}else mp[{x,y}]=0,dir=0;
				}
				else if(dir==2){
					y--;
					if(mp.count({x,y})) ff=1;
					mp[{x,y}]=dir;
					x++;
					if(mp.count({x,y})){
						if(i==n-1 && mp[{x,y}]==0 && x==0 && y==0) f=1;
						else ff=1;
					}else mp[{x,y}]=1,dir=1;
				}else{
					x--;
					if(mp.count({x,y})) ff=1;
					mp[{x,y}]=dir;
					y--;
					if(mp.count({x,y})){
						if(i==n-1 && mp[{x,y}]==0 && x==0 && y==0) f=1;
						else ff=1;
					}else mp[{x,y}]=2,dir=2;
				}
			}else if(s[i]=='R'){
				if(dir==0){
					y++;
					if(mp.count({x,y})) ff=1;
					mp[{x,y}]=dir;
					x++;
					if(mp.count({x,y})){
						if(i==n-1 && mp[{x,y}]==0 && x==0 && y==0) f=1;
						else ff=1;
					}else mp[{x,y}]=1,dir=1;
				}else if(dir==1){
					x++;
					if(mp.count({x,y})) ff=1;
					mp[{x,y}]=dir;
					y--;
					if(mp.count({x,y})){
						if(i==n-1 && mp[{x,y}]==0 && x==0 && y==0) f=1;
						else ff=1;
					}else mp[{x,y}]=2,dir=2;
				}else if(dir==2){
					y--;
					if(mp.count({x,y})) ff=1;
					mp[{x,y}]=dir;
					x--;
					if(mp.count({x,y})){
						if(i==n-1 && mp[{x,y}]==0 && x==0 && y==0) f=1;
						else ff=1;
					}else mp[{x,y}]=3,dir=3;
				}else{
					x--;
					if(mp.count({x,y})) ff=1;
					mp[{x,y}]=dir;
					y++;
					if(mp.count({x,y})){
						if(i==n-1 && mp[{x,y}]==0 && x==0 && y==0) f=1;
						else ff=1;
					}else mp[{x,y}]=0,dir=0;
				}
			}
			if(ff || f) break;
		}
		if(ff) cout << -1 << endl;
		else cout << f << endl;
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值