UVA10618 & POJ1726 & ZOJ2120 - Tango Tango Insurrection(比较烦的DP)

题目链接: UVA10618    POJ1726    ZOJ2120 

【题意】

 
 
【分析】
 
虽然看起来似乎蛮简单,但是自己写的时候错了无数次,唉,具体看代码吧
 
【AC代码】 UVA15ms POJ32ms ZOJ 0ms
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define MAXN 75
#define INF 0x3f3f3f3f
struct NODE{
	int i, l, r, s;
}path[MAXN][4][4][3];
char a[MAXN];
int dp[MAXN][4][4][3], n, buf;//箭头:0-上,1-下,2-左,3-右
//dp[i][a][b][s]表示前i时刻,左脚在a箭头,右脚在b箭头,上一次哪只脚移动了s(0没移动,1左脚移动,2右脚移动)

bool ok(int f, int l, int r, int to)//这里的f用0表示左,1表示右,判断本次移动是否合法
{
	if (0 == f)
	{
		if (to == r) return false;
		if (to == l) return true;
		if (2 == r) return false;
	}
	else
	{
		if (to == l) return false;
		if (to == r) return true;
		if (3 == l) return false;
	}
	return true;
}
int cost(int s, int now, int from, int to)//这里的s,now都是1表示左,2表示右
{
	if (s != now) return 1;
	if (from == to) return 3;
	if ((from == 0 && to == 1) || (from == 1 && to == 0)) return 7;
	if ((from == 2 && to == 3) || (from == 3 && to == 2)) return 7;
	return 5;
}
int dfs(int i, int l, int r, int s)
{
	int& ans = dp[i][l][r][s];
	NODE& p = path[i][l][r][s];
	if (-1 != ans) return ans;
	if (i == n) return ans = 0;
	ans = INF;
	if ('.' == a[i])
	{
		ans = min(ans, dfs(i+1,l,r,0));//不需要踩也不需要移动
		p.i = i + 1, p.l = l, p.r = r, p.s = 0;
		for (int j = 0; j < 4; j++)
		{
			if (ok(0, l, r, j))//左脚移动到j箭头
			{
				buf = dfs(i + 1, j, r, 1) + cost(s,1,l, j);
				if (ans > buf)
					ans = buf, p.i = i + 1, p.l = j, p.r = r, p.s = 1;
			}
			if (ok(1, l, r, j))//右脚移动到j
			{
				buf = dfs(i + 1, l, j, 2) + cost(s,2,r, j);
				if (ans > buf)
					ans = buf, p.i = i + 1, p.l = l, p.r = j, p.s = 2;
			}
		}
		return ans;
	}
	int to;
	switch (a[i])
	{
	case 'U':to = 0; break;
	case 'D':to = 1; break;
	case 'L':to = 2; break;
	case 'R':to = 3; break;
	}
	if (ok(0, l, r, to))//左脚移动到to
	{
		buf = dfs(i + 1, to, r, 1) + cost(s,1,l, to);
		if (ans > buf)
			ans = buf, p.i = i + 1, p.l = to, p.r = r, p.s = 1;
	}
	if (ok(1, l, r, to))//右脚移动到to
	{
		buf = dfs(i + 1, l, to, 2) + cost(s,2,r, to);
		if (ans > buf)
			ans = buf, p.i = i + 1, p.l = l, p.r = to, p.s = 2;
	}
	return ans;
}
void pt(int i, int l, int r, int s)
{
	if (n == i) return;
	NODE& p = path[i][l][r][s];
	if (!p.s)
		printf(".");
	else if (p.s == 1)
		printf("L");
	else
		printf("R");
	pt(p.i, p.l, p.r, p.s);
}
int main()
{
#ifdef SHY
	freopen("e:\\1.txt", "r", stdin);
#endif
	while(scanf("%s%*c", a) && '#' != a[0])
	{
		n = strlen(a);
		memset(dp,-1,sizeof(dp));
		dfs(0, 2, 3, 0);
		pt(0, 2, 3, 0);
		puts("");
	}
	return 0;
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值