UVA10618 跳舞机 Tango Tango Insurrection
cpp
#include<bits/stdc++.h>
using namespace std;
/*
Up-上- 0 Left-左- 1 Down-下- 2 Right-右- 3
根据能量消耗, 逆向dp 计算最优选择:目标dp[0][1][3][0]
dp(i,a,b,s)表示踩第i个箭头,左脚在a上,右脚在b上,上一个移动的脚为s
(s: 0-没有脚移动;1-左脚移动;2-右脚移动)
*/
const int UP = 0, LEFT = 1, RIGHT = 2, DOWN = 3;
const int MAXN = 105;
const int INF = 0x3f3f3f3f;//无穷大
int n;
char in[MAXN];//存储输入
int dp[MAXN][4][4][3];
int action[MAXN][4][4][3];//记录决策(压缩存储)
int pos[MAXN];//字符转编号
char foot[] = ".LR";
int move_energy(int from, int to) {// 单脚连续两次移动的能量
if (from == to) return 3;
if (from + to == 3) return 7;
return 5;
}
int energy(int a, int b, int s, int f, int t, int ta, int tb) {
// 非法状态判断
if (ta == tb) return -1;
if (ta == RIGHT && tb == LEFT) return -1;
if (a == RIGHT && tb != b) return -1; // 左脚在右箭头上时,右脚不能动
if (b == LEFT && ta != a) return -1; // 右脚在左箭头上时,左脚不能动
// 能量计算
int e = 0;
if(f == 0) e = 0; // 不动
else if (f != s) e = 1; // 换脚
else { // 同脚连踩
if (f == 1) e = move_energy(a, ta);
else e = move_energy(b, tb);
}
return e;
}
void update(int i, int a, int b, int s, int f, int t) {
int ta = a,tb = b;//ta-左脚新位置 与tb-右脚新位置
if(f == 1) ta = t;//左脚移动到t
else if(f == 2) tb = t;//右脚移动到t
int e = energy(a, b, s, f, t, ta, tb);//计算能量消耗
if (e < 0) return;
//计算能量花费并更新当前dp为最小值
int cost = dp[i+1][ta][tb][f] + e;
if (cost < dp[i][a][b][s]){
dp[i][a][b][s] = cost;
action[i][a][b][s] = f * 4 + t; // 压缩存储
}
}
void solve(){
n = strlen(in);
memset(dp,0,sizeof(dp));//dp初始化
memset(action, 0, sizeof(action));//action初始化
//逆推
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++){ //上一次移动的是哪只脚(都没动 or 左脚动 or 右脚动)
dp[i][a][b][s] = INF;//初始化为无穷大,方便记录最小能量消耗时的状态
if(in[i] == '.'){//当前是空拍 '.'
update(i,a,b,s,0,0);//不动
for (int t = 0;t < 4;t++){//动(左 or 右)脚到t ,为下一步做准备
update(i, a, b, s, 1, t);//左脚动
update(i, a, b, s, 2, t);//右脚动
}
}else{
int t = pos[in[i]];//当前目标方向
update(i, a, b, s, 1, t);//左脚动
update(i, a, b, s, 2, t);//右脚动
}
}
}
}
}
// 输出方案
int a = LEFT, b = RIGHT, 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", foot[f]);
s = f;
if (f == 1) a = t;
else if (f == 2) b = t;
}
printf("\n");
}
int main(){
pos['U'] = UP; pos['L'] = LEFT; pos['R'] = RIGHT; pos['D'] = DOWN;
while(scanf("%s",in) == 1){
if (in[0] == '#') break;
solve();
}
}