csu 1510 Happy Robot(字符串DP,记忆化搜索)

Happy RobotTime 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

题意:给一个字符串,包含有四种字符,F表示向前走,L表示在当前位置向左转,R表示在当前位置向右转,?表示执行上面三种任意一种都可以

机器人从(0,0)开始,输出x,y的最小值和最大值

思路:用记忆化搜索从后往前搜索,搜过的位置可以直接返回。DP里要保存在当前这个位置朝向某个方向极值

队友还提供了一种字符串DP的思路,其实也差不多。

关键在于此题不能在二维平面考虑,要在字符串上考虑才可以。

这里给出两个代码,记忆化搜索的方向是上下左右,字符串DP的方向是上右下左

代码1:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
#define N 1050
#define INF 99999999
struct Node
{
    int minx,maxx,miny,maxy;
} dp[N][4];
char a[N];
int vis[N][4];
int len;
int Min(int b,int c,int d)
{
    if(b>c) b=c;
    return b<d?b:d;
}
int Max(int b,int c,int d)
{
    if(b<c) b=c;
    return b>d?b:d;
}
Node dfs(int k,int f)
{
    if(vis[k][f]) return dp[k][f];
    vis[k][f]=1;
    dp[k][f].minx=dp[k][f].maxx=dp[k][f].miny=dp[k][f].maxy=0;
    if(k==len-1)
    {
        if(a[k]=='F')
        {
            if(f==0) dp[k][f].maxy=1,dp[k][f].miny=1;
            else if(f==1) dp[k][f].maxy=-1,dp[k][f].miny=-1;
            else if(f==2) dp[k][f].minx=-1,dp[k][f].maxx=-1;
            else dp[k][f].minx=1,dp[k][f].maxx=1;
        }
        else if(a[k]=='?')
        {
            if(f==0) dp[k][f].maxy=1;
            else if(f==1) dp[k][f].miny=-1;
            else if(f==2) dp[k][f].minx=-1;
            else dp[k][f].maxx=1;
        }
    }
    else
    {
        if(a[k]=='L')
        {
            if(f==0) dp[k][f]=dfs(k+1,2);
            else if(f==1) dp[k][f]=dfs(k+1,3);
            else if(f==2) dp[k][f]=dfs(k+1,1);
            else dp[k][f]=dfs(k+1,0);
        }
        else if(a[k]=='R')
        {
            if(f==0) dp[k][f]=dfs(k+1,3);
            else if(f==1) dp[k][f]=dfs(k+1,2);
            else if(f==2) dp[k][f]=dfs(k+1,0);
            else dp[k][f]=dfs(k+1,1);
        }
        else if(a[k]=='F')
        {
            if(f==0)
            {
                dp[k][f]=dfs(k+1,0);
                dp[k][f].maxy++;
                dp[k][f].miny++;
            }
            else if(f==1)
            {
                dp[k][f]=dfs(k+1,1);
                dp[k][f].miny--;
                dp[k][f].maxy--;
            }
            else if(f==2)
            {
                dp[k][f]=dfs(k+1,2);
                dp[k][f].minx--;
                dp[k][f].maxx--;
            }
            else
            {
                dp[k][f]=dfs(k+1,3);
                dp[k][f].maxx++;
                dp[k][f].minx++;
            }
        }
        else
        {
            Node b,c,d,e;
            if(f==0)
            {
                b=dfs(k+1,0);
                b.maxy++; b.miny++;
                c=dfs(k+1,2);
                d=dfs(k+1,3);
                dp[k][f].minx=Min(b.minx,c.minx,d.minx);
                dp[k][f].maxx=Max(b.maxx,c.maxx,d.maxx);
                dp[k][f].miny=Min(b.miny,c.miny,d.miny);
                dp[k][f].maxy=Max(b.maxy,c.maxy,d.maxy);
            }
            else if(f==1)
            {
                b=dfs(k+1,1);
                b.maxy--;  b.miny--;
                c=dfs(k+1,3);
                d=dfs(k+1,2);
                dp[k][f].minx=Min(b.minx,c.minx,d.minx);
                dp[k][f].maxx=Max(b.maxx,c.maxx,d.maxx);
                dp[k][f].miny=Min(b.miny,c.miny,d.miny);
                dp[k][f].maxy=Max(b.maxy,c.maxy,d.maxy);
            }
            else if(f==2)
            {
                b=dfs(k+1,2);
                b.maxx--; b.minx--;
                c=dfs(k+1,1);
                d=dfs(k+1,0);
                dp[k][f].minx=Min(b.minx,c.minx,d.minx);
                dp[k][f].maxx=Max(b.maxx,c.maxx,d.maxx);
                dp[k][f].miny=Min(b.miny,c.miny,d.miny);
                dp[k][f].maxy=Max(b.maxy,c.maxy,d.maxy);
            }
            else
            {
                b=dfs(k+1,3);
                b.maxx++; b.minx++;
                c=dfs(k+1,0);
                d=dfs(k+1,1);
                dp[k][f].minx=Min(b.minx,c.minx,d.minx);
                dp[k][f].maxx=Max(b.maxx,c.maxx,d.maxx);
                dp[k][f].miny=Min(b.miny,c.miny,d.miny);
                dp[k][f].maxy=Max(b.maxy,c.maxy,d.maxy);
            }
        }
    }
    return dp[k][f];
}
int main()
{
    int cas=1;
    while(~scanf("%s",a))
    {
        len=strlen(a);
        memset(vis,0,sizeof(vis));
        Node ans=dfs(0,3);
        printf("Case %d: %d %d %d %d\n",cas++,ans.minx,ans.maxx,ans.miny,ans.maxy);
    }
    return 0;
}

代码2:

#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、付费专栏及课程。

余额充值