题目大意
描述
跳舞机的踏板上有四个箭头:上下左右。当舞曲开始的时候,你需要在箭头移动到踏板上的时候,你需要在踏板上踩下相同的箭头。
不需要踩箭头的时候,踩箭头不会受到惩罚,当时需要踩箭头的时候,必须踩一下
踩箭头需要消耗能量,写一个程序来帮助选择轻松的踩踏方式,使得消耗的能量最少。
消耗能量:
- 如果这个脚上个时间没有任何动作,消耗1单位能量
- 如果这个脚上个时间没有移动,消耗3单位能量
- 如果这个脚上个时间移动到相邻箭头,消耗5单位能量
- 如果这个脚上个时间移动到相对箭头,消耗7单位能量
正常情况下,左脚不能放到右箭头上,但是有一种情况例外:当你的左脚在上箭头或者下箭头,你可以临时扭着身子用右脚踩左箭头,但是在右脚移动之前,左脚不能动。
输入
最多100组数据,每组数据包含一个长度不超过70的字符串。L
和R
表示左右箭头,.
表示不需要踩箭头,U
和D
表示上下箭头。
输出
和输入一样长度的字符串,表示每个时间执行动作的脚,L
和R
表示左右脚,.
表示不踩。
Sample Input
LRLRLLLLRLRLRRRRLLRRLRLDU…D…UUUUDDDD
#
Sample Output
LRLRLLLLRLRLRRRRLLRRLRLRL…R…LLLLRRRR
思路
dp(i,a,b,s)
表示已经踩了i个箭头。
左右脚分别在箭头a和箭头b上,
上一个周期移动的脚为s(s=0表示脚没有移动,s=1表示左脚移动,s=2表示右脚移动)
如果下一步是.
,有三种决策:
- 左脚移动到另一个箭头上
- 右脚移动到另一个箭头上
- 不动
如果下一步是4个箭头之一,有两种决策:
- 左脚移动到该箭头
- 右脚移动到该箭头。
代码
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
#define maxn 100
char S[maxn];
int dp[maxn][4][4][3];
int action[maxn][4][4][3]; //将移动哪只脚以及方向变成一个整数存进数组
const int LEFT = 1;
const int RIGHT = 2;
int pos[256];
int energy(int l,int tl)
{
if (l == tl) return 3; // 相同的位置
if (l + tl == 3) return 7; // 相对的位置
return 5; // 相邻的位置
}
//l左脚的位置
//r右脚的位置
//m决策
//f左脚或者右脚
//t上下左右
int energy(int l,int r,int m,int f,int t,int &tl,int &tr) //
{
tl = l;
tr = r;
if (f == 1)//左脚
tl = t;
else if (f == 2)//右脚
tr = t;
if (tl == tr) return -1; // 下一个状态踩到同一个位置
if (tl == RIGHT && tr == LEFT) return -1; // 背向跳舞机
if (l == RIGHT && tr != r) return -1; // l左脚在右脚的位置,但是移动了右脚,无论移动到哪儿,都是不合法的
if (r == LEFT && tl != l) return -1; // r右脚在左脚的位置,但是移动了左脚,无论移动到哪儿,都是不合法的
int e = 0;
if (f == 0) // 没有脚移动
e = 0;
else if (f != m) //上一次移动的脚不是现在移动的脚
e = 1;
else
{
if (f == 1) // 移动的是左脚,
e = energy(l,tl);
else // 移动的是右脚
e = energy(r,tr);
}
return e;
}
//第i个位置
//l左脚的位置
//r右脚的位置
//m决策
//f左脚或者右脚
//t上下左右
void update(int i,int l,int r,int m,int f,int t)
{
int tl,tr;
int e;
e = energy(l,r,m,f,t,tl,tr);
if (e < 0)
return ;
int cost = dp[i+1][tl][tr][f] + e;
int &ans = dp[i][l][r][m];
if (ans > cost)
{
ans = cost;
action[i][l][r][m] = f * 4 + t;//将左脚或者右脚以及上下左右组合成一个整数
}
}
int main ()
{
pos['U'] = 0;
pos['D'] = 3;
pos['L'] = 1;
pos['R'] = 2;
char place[] = ".LR";
while(scanf("%s",S))
{
if(S[0] == '#') break;
int len = strlen(S);
memset(dp,0,sizeof(dp));
for(int i = len-1; i>=0; i--)
{
for(int l = 0; l<4; l++)
{
for(int r = 0; r<4; r++)
{
if(l == r ) continue;
for(int m = 0; m<3; m++)
{
dp[i][l][r][m] = 0x1f1f1f1f;
if(S[i] == '.')//3种决策
{
update(i,l,r,m,0,0);//不动
for(int t = 0; t < 4; t++)
{
update(i,l,r,m,1,t);//移动左脚 移动到位置t
update(i,l,r,m,2,t);//移动右脚 移动到位置t
}
}
else//2种决策
{
update(i,l,r,m,1,pos[S[i]]);//左脚移动到位置S[i]
update(i,l,r,m,2,pos[S[i]]);//右脚移动到位置S[i]
}
}
}
}
}
int l = 1;
int r = 2;
int m = 0;
for (int i = 0 ; i < len ; i++)
{
int f = action[i][l][r][m] / 4;
int t = action[i][l][r][m] % 4;
printf("%c",place[f]);
m = f;
if (f == 1)
l = t;
else if (f == 2)
{
r = t;
}
}
puts("");
//printf("%d\n",d[0][1][2][0]);
}
}
Hit
状态比较复杂