// 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;
}
uva 10618 Tango Tango Insurrection 动态规划
最新推荐文章于 2022-03-28 00:09:02 发布