题意长且烦:
https://vjudge.net/problem/UVA-1252
思路:信息量太杂,理不过来…
看了LRJ大佬的代码,nb。
定义状态:d[i][a][b][s]:已经踩了 i 个箭头,左右脚在a,b上,上一时刻移动的脚是s。
当字母是’.'时,有3种决策:不动,左脚移动,右脚移动。
当字母是箭头时:有2种决策,左脚移动到目标,右脚移动到目标。
能量的计算: t 时刻的能量需要参看 t-1 时刻的状态。比如,如果t-1时刻动的是左脚,那么如果t时刻还动左脚的话,有3种情况:移动到自身(3);移动到相邻(5);移动到对面(7)。如果t时刻动的是右脚,能量为1。
从后往前递推,并记录下每一步移动的脚。结果是d[0][1][2][0]。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int UP = 0;
const int LEFT = 1;
const int RIGHT = 2;
const int DOWN = 3;
const int maxn = 70 + 5;
//d[i][a][b][s]: 已经踩了 i 个箭头,左右脚在a,b上,上一时刻移动的脚是s
//s: 0-没移动;1-左脚移动;2-右脚移动
int d[maxn][4][4][3], n;
// 如果动作是把f脚移动到t,action = f * 4 + t;
int action[maxn][4][4][3];
char seq[maxn], pos[256], footch[] = ".LR";
// 某只脚的连续第二次移动
int energy(int a, int ta){
if(a == ta) return 3;
if(a + ta == 3) return 7;
return 5;
}
// 状态(i,a,b,s)下,把 f脚 移动到t所花费的最少能量。ta,tb是这次移动之后的左右脚位置。
int energy(int i, int a, int b, int s, int f, int t, int& ta, int& tb){
ta = a; tb = b;
if(f == LEFT) ta = t; // 如果移动的是左脚,更新左脚位置
else if(f == RIGHT) tb = t;
// 判断移动是否合理
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 ;
if(f == 0) e = 0; // 不移动
else if(f != s) e = 1; // 这只脚上次没移动
else {
if(f == LEFT) e = energy(a, ta);
else e = energy(b, tb);
}
return e;
}
// 状态(i,a,b,s)下,把f移动到t
void update(int i, int a, int b, int s, int f, int t){
int ta,tb;
int e = energy(i, 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(cost < ans){
ans = cost;
action[i][a][b][s] = f * 4 + t;
}
}
void solve(){
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)
for(int s = 0; s < 3; ++s){
d[i][a][b][s] = 10*n;
if(seq[i] == '.'){
update(i,a,b,s, 0, 0); // 不动
for(int t = 0; t < 4; ++t){
update(i,a,b,s, LEFT, t); // 动左脚
update(i,a,b,s, RIGHT, t); // 动右脚
}
}
else{
update(i,a,b,s,LEFT,pos[seq[i]]); // 动左脚
update(i, a, b, s, RIGHT, pos[seq[i]]); // 动右脚
}
}
}
void print_solution(){
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",footch[f]);
s = f;
if(f == LEFT) a = t;
else if(f == RIGHT) b = t;
}
printf("\n");
}
int main()
{
freopen("in.txt","r",stdin);
pos['U'] = 0; pos['L'] = 1; pos['R'] = 2; pos['D'] = 3;
while(scanf("%s",seq) == 1){
if(seq[0] == '#') break;
n = strlen(seq);
memset(d, 0, sizeof(d));
solve();
print_solution();
}
return 0;
}