【GDOI2022PJD2T4 机器人】题解

D2T4 机器人

题目

刚上初一的小纯特别喜欢机器人,这周末,她报名了学校的“小机器人俱乐部”,而进入俱乐部需要通过一场考试。

考试场地可以看作一个 \(n \times m\) 的网格图,行从上往下标号为 \(1, \dots, n\),列从左往右标号为 \(1, \dots , m\)。每个格子有三种可能:空地,障碍物,机器人(有且只有一个),分别用“.”、“*”、“R”表示。现在小纯需要控制机器人在考试场地上行走,她每秒可以发送一条指令,为“W”——往上走、“S”——往下走、“A”——往左走、“D”——往右走的其中之一。由于俱乐部的机器人是避障机器人,当机器人接收到一条指令的时候,如果即将到达的位置为障碍物,那么机器人将留在原地,否则机器人向对应方向走一步。如果其走出边界则考试失败(例如在第一行发送指令向上走)。

为了增加考试的难度,俱乐部提供的机器人的信号接收器都存在问题。换言之,对于小纯给出的每一条指令,机器人有可能接收到指令并执行,也有可能接收不到指令并保持不动。现在小纯提供了一个指令序列,她想知道,这个指令序列是否存在某些情况使得这个指令序列走出边界。

image

思路

对于每个格子,显然,我们越早到这个格子是越优的。

基于此,我们可以对第一个点入队,查找它通往上下左右点最早在哪里,跑个最短路即可。

最后用Dij+优先队列优化,如果跑出格子了就输出 YES

代码

#include<bits/stdc++.h>
using namespace std;
//#define int long long
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'
){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x
<<3)+(ch^48);ch=getchar();}return x*f;}
#define N 610
#define M 200010
//#define mo
struct node
{
	int x, y, z; 
	bool operator <(const node &A) const
	{
		return z>A.z; 
	}
}p; 
int n, m, i, j, k, T;
int dx[4]={-1, 1, 0, 0}; 
int dy[4]={0, 0, -1, 1}; 
char s[N][N], c[M]; 
int a[N][N], nxt[M][5], len; 
int ax, bx, cx, ex, sx, sy; 
int x, y, z, newx, newy, flg;  
priority_queue<node>q; 

void init()
{
	ax=bx=cx=ex=flg=i=j=k=len=m=n=newx=newy=sx=sy=x=y=z=0; 
	memset(a, -1, sizeof(a)); 
	memset(c, 0, sizeof(c)); 
	memset(s, 0, sizeof(s)); 
	memset(nxt, 0, sizeof(nxt)); 
	while(!q.empty())  q.pop(); 
}

signed main()
{
//	freopen("robot.in", "r", stdin);
//	freopen("robot.out", "w", stdout);
	T=read(); 
	while(T--)
	{
		init(); 
		scanf("%s", c+1); len=strlen(c+1); 
		n=read(); m=read(); 
		for(i=1; i<=n; ++i) 
		{
			scanf("%s", s[i]+1); 
			for(j=1; j<=m; ++j)
				if(s[i][j]=='R') sx=i, sy=j; 
		}
		ax=bx=cx=ex=0; 
		for(i=len; i>=0; --i)
		{
			nxt[i][0]=ax; nxt[i][1]=bx; 
			nxt[i][2]=cx; nxt[i][3]=ex; 
			if(c[i]=='W') ax=i; 
			if(c[i]=='S') bx=i; 
			if(c[i]=='A') cx=i; 
			if(c[i]=='D') ex=i; 
		}
//		for(i=0; i<=len; ++i)
//			printf("%d %d %d %d\n", nxt[i][0], nxt[i][1], nxt[i][2], nxt[i][3]); 
		p.x=sx; p.y=sy; p.z=0; 
		q.push(p); 
		while(!q.empty())
		{
			p=q.top(); q.pop(); 
			if(a[x=p.x][y=p.y]!=-1) continue; 
			a[x][y]=z=p.z; 
			for(i=0; i<4; ++i)
			{
				if(!nxt[z][i]) continue; 
				newx=x+dx[i]; 
				newy=y+dy[i]; 
				if(a[newx][newy]!=-1) continue; 
				if(s[newx][newy]=='*') continue; 
				if(newx<1 || newy<1 || newx>n || newy>m)
				{
					printf("YES\n"); flg=1; 
					break; 
				}
				p.x=newx; p.y=newy; p.z=nxt[z][i]; 
				q.push(p); 
			}
			if(flg) break; 
		}
//		for(i=1; i<=n; ++i, printf("\n")) 
//			for(j=1; j<=m; ++j) printf("%2d ", a[i][j]); 
		if(!flg) printf("NO\n"); 
	}
	return 0;
}

总结

这题思维难度中等,想起来有一定难度。

对于每个格子,我们要考虑其最优情况是怎样,想清这一点,就迎刃而解了。

多测队列要清空!我因此没了90分。

posted @ 2022-04-25 17:59  zhangtingxi  阅读(116)  评论(0编辑  收藏  举报