CSU 1510 Happy Robot(字符串上的dp)

本文介绍了一种解决机器人路径极值问题的方法,通过四个不同的动态规划过程来确定机器人在未知初始方向的情况下能达到的坐标极值。这种方法避免了直接在平面上进行搜索,从而大大减少了计算复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Time Limit: 1 Sec   Memory Limit: 128 MB
Submit: 182   Solved: 85
[ Submit][ Status][ Web Board]

Description

Input

There will be at most 1000 test cases. Each case contains a command sequence with no more than 1000 characters.

Output

For each test case, print the case number, followed by minimal/maximal possible x (in this order), then the minimal/maximal possible y.

Sample Input

F?F
L??
LFFFRF

Sample Output

Case 1: 1 3 -1 1
Case 2: -1 1 0 2

Case 3: 1 1 3 3

解题思路:

这题坑的地方就在于不能够往平面上去想,最开始是dp[x][y][d]表示在坐标(x,y)位置,方向为d,得到的坐标极值。

但肯定超时。。。

所以只能够聪明一点,对字符串做dp了。。

dp[i][j]表示到达第i个字符的命令,此时机器人的方向为j时得到的坐标极值,状态表示出来了,方程就很简单了。。

由于要求Xmin,Xmax,Ymin,Ymax,所以四次DP即可。。

#include<iostream>
#include<cstdio>
#include<cstring>
#define max(a,b) (a) > (b) ? (a) : (b)
#define min(a,b) (a) < (b) ? (a) : (b)
using namespace std;

const int maxn = 1005;
const int inf = 0x3f3f3f3f;
int dp[maxn][4],n;
char str[maxn];

int MAX(int a,int b,int c,int d)
{
	return max(a,max(b,max(c,d)));
}

int MIN(int a,int b,int c,int d)
{
	return min(a,min(b,min(c,d)));
}

void DP1()
{
	for(int i = 0; i < n; i++)
		for(int j = 0; j < 4; j++)
			dp[i][j] = inf;
	if(str[0] == 'F')
		dp[0][1] = 1;
	else if(str[0] == 'L')
		dp[0][0] = 0;
	else if(str[0] == 'R')
		dp[0][2] = 0;
	else 
	{
		dp[0][0] = 0;
		dp[0][1] = 1;
		dp[0][2] = 0;
	}
	for(int i = 1; i < n; i++)
		for(int j = 0; j < 4; j++) //上一个指令执行后的方向
		{
			if(str[i] == 'F') //前进	
			{
				if(j == 0) //向上
					dp[i][j] = min(dp[i][j],dp[i-1][j]);
				else if(j == 1) //向右
					dp[i][j] = min(dp[i][j],dp[i-1][j] + 1);
				else if(j == 2) //向下
					dp[i][j] = min(dp[i][j],dp[i-1][j]);
				else //向左
					dp[i][j] = min(dp[i][j],dp[i-1][j] - 1);
			}
			else if(str[i] == 'L')
			{
				int d = ((j - 1) % 4 + 4) % 4;
				dp[i][d] = min(dp[i][d],dp[i-1][j]);
			}
			else if(str[i] == 'R')
			{
				int d = (j + 1) % 4;
				dp[i][d] = min(dp[i][d],dp[i-1][j]);
			}
			else
			{
				if(j == 0) //向上
					dp[i][j] = min(dp[i][j],dp[i-1][j]);
				else if(j == 1) //向右
					dp[i][j] = min(dp[i][j],dp[i-1][j] + 1);
				else if(j == 2) //向下
					dp[i][j] = min(dp[i][j],dp[i-1][j]);
				else //向左
					dp[i][j] = min(dp[i][j],dp[i-1][j] - 1);
				int d = ((j - 1) % 4 + 4) % 4;
				dp[i][d] = min(dp[i][d],dp[i-1][j]);
				d = (j + 1) % 4;
				dp[i][d] = min(dp[i][d],dp[i-1][j]);
			}
		}
}

void DP2()
{
	for(int i = 0; i < n; i++)
		for(int j = 0; j < 4; j++)
			dp[i][j] = -inf;
	if(str[0] == 'F')
		dp[0][1] = 1;
	else if(str[0] == 'L')
		dp[0][0] = 0;
	else if(str[0] == 'R')
		dp[0][2] = 0;
	else 
	{
		dp[0][0] = 0;
		dp[0][1] = 1;
		dp[0][2] = 0;
	}
	for(int i = 1; i < n; i++)
		for(int j = 0; j < 4; j++) //上一个指令执行后的方向
		{
			if(str[i] == 'F') //前进	
			{
				if(j == 0) //向上
					dp[i][j] = max(dp[i][j],dp[i-1][j]);
				else if(j == 1) //向右
					dp[i][j] = max(dp[i][j],dp[i-1][j] + 1);
				else if(j == 2) //向下
					dp[i][j] = max(dp[i][j],dp[i-1][j]);
				else //向左
					dp[i][j] = max(dp[i][j],dp[i-1][j] - 1);
			}
			else if(str[i] == 'L')
			{
				int d = ((j - 1) % 4 + 4) % 4;
				dp[i][d] = max(dp[i][d],dp[i-1][j]);
			}
			else if(str[i] == 'R')
			{
				int d = (j + 1) % 4;
				dp[i][d] = max(dp[i][d],dp[i-1][j]);
			}
			else
			{
				if(j == 0) //向上
					dp[i][j] = max(dp[i][j],dp[i-1][j]);
				else if(j == 1) //向右
					dp[i][j] = max(dp[i][j],dp[i-1][j] + 1);
				else if(j == 2) //向下
					dp[i][j] = max(dp[i][j],dp[i-1][j]);
				else //向左
					dp[i][j] = max(dp[i][j],dp[i-1][j] - 1);
				int d = ((j - 1) % 4 + 4) % 4;
				dp[i][d] = max(dp[i][d],dp[i-1][j]);
				d = (j + 1) % 4;
				dp[i][d] = max(dp[i][d],dp[i-1][j]);
			}
		}
}

void DP3()
{
	for(int i = 0; i < n; i++)
		for(int j = 0; j < 4; j++)
			dp[i][j] = inf;
	if(str[0] == 'F')
		dp[0][1] = 0;
	else if(str[0] == 'L')
		dp[0][0] = 0;
	else if(str[0] == 'R')
		dp[0][2] = 0;
	else 
	{
		dp[0][0] = 0;
		dp[0][1] = 0;
		dp[0][2] = 0;
	}
	for(int i = 1; i < n; i++)
		for(int j = 0; j < 4; j++) //上一个指令执行后的方向
		{
			if(str[i] == 'F') //前进	
			{
				if(j == 0) //向上
					dp[i][j] = min(dp[i][j],dp[i-1][j] + 1);
				else if(j == 1) //向右
					dp[i][j] = min(dp[i][j],dp[i-1][j]);
				else if(j == 2) //向下
					dp[i][j] = min(dp[i][j],dp[i-1][j] - 1);
				else //向左
					dp[i][j] = min(dp[i][j],dp[i-1][j]);
			}
			else if(str[i] == 'L')
			{
				int d = ((j - 1) % 4 + 4) % 4;
				dp[i][d] = min(dp[i][d],dp[i-1][j]);
			}
			else if(str[i] == 'R')
			{
				int d = (j + 1) % 4;
				dp[i][d] = min(dp[i][d],dp[i-1][j]);
			}
			else
			{
				if(j == 0) //向上
					dp[i][j] = min(dp[i][j],dp[i-1][j] + 1);
				else if(j == 1) //向右
					dp[i][j] = min(dp[i][j],dp[i-1][j]);
				else if(j == 2) //向下
					dp[i][j] = min(dp[i][j],dp[i-1][j] - 1);
				else //向左
					dp[i][j] = min(dp[i][j],dp[i-1][j]);
				int d = ((j - 1) % 4 + 4) % 4;
				dp[i][d] = min(dp[i][d],dp[i-1][j]);
				d = (j + 1) % 4;
				dp[i][d] = min(dp[i][d],dp[i-1][j]);
			}
		}
}

void DP4()
{
	for(int i = 0; i < n; i++)
		for(int j = 0; j < 4; j++)
			dp[i][j] = -inf;
	if(str[0] == 'F')
		dp[0][1] = 0;
	else if(str[0] == 'L')
		dp[0][0] = 0;
	else if(str[0] == 'R')
		dp[0][2] = 0;
	else 
	{
		dp[0][0] = 0;
		dp[0][1] = 0;
		dp[0][2] = 0;
	}
	for(int i = 1; i < n; i++)
		for(int j = 0; j < 4; j++) //上一个指令执行后的方向
		{
			if(str[i] == 'F') //前进	
			{
				if(j == 0) //向上
					dp[i][j] = max(dp[i][j],dp[i-1][j] + 1);
				else if(j == 1) //向右
					dp[i][j] = max(dp[i][j],dp[i-1][j]);
				else if(j == 2) //向下
					dp[i][j] = max(dp[i][j],dp[i-1][j] - 1);
				else //向左
					dp[i][j] = max(dp[i][j],dp[i-1][j]);
			}
			else if(str[i] == 'L')
			{
				int d = ((j - 1) % 4 + 4) % 4;
				dp[i][d] = max(dp[i][d],dp[i-1][j]);
			}
			else if(str[i] == 'R')
			{
				int d = (j + 1) % 4;
				dp[i][d] = max(dp[i][d],dp[i-1][j]);
			}
			else
			{
				if(j == 0) //向上
					dp[i][j] = max(dp[i][j],dp[i-1][j] + 1);
				else if(j == 1) //向右
					dp[i][j] = max(dp[i][j],dp[i-1][j]);
				else if(j == 2) //向下
					dp[i][j] = max(dp[i][j],dp[i-1][j] - 1);
				else //向左
					dp[i][j] = max(dp[i][j],dp[i-1][j]);
				int d = ((j - 1) % 4 + 4) % 4;
				dp[i][d] = max(dp[i][d],dp[i-1][j]);
				d = (j + 1) % 4;
				dp[i][d] = max(dp[i][d],dp[i-1][j]);
			}
		}
}

int main()
{
	int cas = 1;
	while(scanf("%s",str)!=EOF)
	{
		n = strlen(str);
		DP1();
		printf("Case %d: %d ",cas++,MIN(dp[n-1][0],dp[n-1][1],dp[n-1][2],dp[n-1][3]));
		DP2();
		printf("%d ",MAX(dp[n-1][0],dp[n-1][1],dp[n-1][2],dp[n-1][3]));
		DP3();
		printf("%d ",MIN(dp[n-1][0],dp[n-1][1],dp[n-1][2],dp[n-1][3]));
		DP4();
		printf("%d\n",MAX(dp[n-1][0],dp[n-1][1],dp[n-1][2],dp[n-1][3]));
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值