您的位置:首页 > 编程语言 > Go语言

uva 10618 Tango Tango Insurrection 动态规划

2015-09-16 17:51 393 查看
//	uva 10618 Tango Tango Insurrection 动态规划
//
//	解题思路:
//		
//		这是看的条件最多的一个动态规划了.看了很久很久,虽然
//	状态很好理解,但是限制特别多.
//		d[i][a][b][s]表示到达第i个指示灯的时候,左脚在a,右脚
//	在b,上一次移动的脚为s(没有移动0,左脚1,右脚2)所需的最小花
//	费.并将四个方向分别编号为上0,下3,左1,右2.这样编码的方式
//	对于求相对的方向只要和为3即可.
//		状态转移如下:
//			如果当前是'.'.可以选择不动,左脚移到其他方向,或者
//		右脚移动到其他方向.
//			如果当前是某一个方向,则左脚移动到该位置上,右脚移
//		动到该位置上.
//	采用逆推的方法.
//
//	详细的细节请看程序.大神的code十分的优雅,而且十分的巧妙,在
//	这里向刘老师致敬~~~~

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

const int LEFT = 1;
const int RIGHT = 2;

const int MAXN = 108;
int n;
int d[MAXN][4][4][3];
char seq[MAXN];
int action[MAXN][4][4][3]; // 将移动哪只脚以及方向变成一个整数存进数组
char place[] = ".LR";
int pos[256];

int energy(int a,int ta){
	if (a == ta)	return 3; // 相同的位置
	if (a + ta == 3)	return 7; // 相对的位置
	return 5;	// 相邻的位置
}

int energy(int a,int b,int s,int f,int t,int &ta,int &tb){
	ta = a;
	tb = b;

	if (f == 1)
		ta = t;
	else if (f == 2) 
		tb = t;

	if (ta == tb)	return -1; // 下一个状态猜到同一个位置
	if (ta == RIGHT && tb == LEFT) return -1; // 背向跳舞机
	if (a == RIGHT && tb != b)	return -1; // a左脚在右脚的位置,但是移动了右脚,无论移动到哪儿,都是不合法的
	if (b == LEFT  && ta != a)	return -1; // b右脚在左脚的位置,但是移动了右脚,无论一定到哪儿,都是不合法的

	int e = 0;
	
	if (f == 0) // 没有脚移动
		e = 0;
	else if (f != s) //上一次移动的脚不是现在移动的脚
		e = 1;
	else {
		if (f == 1) // 移动的是左脚,
			e = energy(a,ta);
		else		// 移动的是右脚
			e = energy(b,tb);
	}
	return e;

}

void update(int i,int a,int b,int s,int f,int t){
	int ta,tb;
	int e;
	e = energy(a,b,s,f,t,ta,tb);

	if (e < 0)
		return ;

	int cost = d[i+1][ta][tb][f] + e;

	int &ans = d[i][a][b][s];

	if (ans > cost){
		ans = cost;
		action[i][a][b][s] = f * 4 + t; 
	}

}

void solve(){
	n = strlen(seq);
	memset(d,0,sizeof(d));

	for (int i = n-1;i >=0 ;i --){
		for (int a = 0; a < 4 ;a ++ ){
			for (int b = 0; b < 4; b ++){
				if (a == b)
					continue;

				for (int s = 0; s < 3; s++){
					d[i][a][b][s] = 0x1f1f1f1f;
					if (seq[i] == '.'){

						update(i,a,b,s,0,0);

						for (int t = 0 ; t < 4; t++){
							update(i,a,b,s,1,t);
							update(i,a,b,s,2,t);
						}
					}else {
						
						update(i,a,b,s,1,pos[seq[i]]);
						update(i,a,b,s,2,pos[seq[i]]);

					}
				}

			}
		}
	}

	int a = 1;
	int b = 2;
	int s = 0;
	for (int i = 0 ;i < n ; i++){
		int f = action[i][a][b][s] / 4;
		int t = action[i][a][b][s] % 4;

		printf("%c",place[f]);

		s = f;

		if (f == 1)
			a = t;
		else if (f == 2){
			b = t;
		}
	}
	puts("");
	//printf("%d\n",d[0][1][2][0]);

}

int main(){
	pos['U'] = 0;
	pos['D'] = 3;
	pos['L'] = 1;
	pos['R'] = 2;
	//freopen("1.txt","r",stdin);
	while(scanf("%s",seq)!=EOF){
		if (seq[0] == '#')
			break;

		solve();
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: