10618 - Tango Tango Insurrection

Problem A: Tango Tango Insurrection

这里写图片描述这里写图片描述
You are attempting to learn to play a simple arcade dancing game. The game has 4 arrows set into a pad: Up, Left, Down, Right. While a song plays, you watch arrows rise on a screen, and when they hit the top, you have to hit the corresponding arrows on the pad. There is no penalty for stepping on an arrow without need, but note that merely standing on an arrow does not activate it; you must actually tap it with your foot. Many sequences in the game are very fast-paced, and require proper footwork if you don’t want to tire yourself out. Write a program to determine the easiest way to execute a certain sequence of arrows.
We will work with a basic time unit of an eighth-note. At any given time, your left foot and right foot will each be on distinct arrows. Only one foot may perform an action (changing arrows and/or tapping) during any time unit; jumping is not allowed. Also, you must remain facing forward in order to see the screen. This puts limitations on which feet you can use to hit which arrows. Finally, hitting two arrows in a row with the same foot (“double-tapping”) is exhausting, because you can’t shift your weight onto that foot. Ideally, you want to alternate feet all the way through a string of consecutive arrows.

Performing an action with a foot costs 1 unit of energy if it did NOT perform an action in the previous time unit. If it did, then it costs 3 units if it doesn’t change arrows, 5 units if it moves to an adjacent arrow, and 7 units if it moves directly across the pad (between Up and Down, or Left and Right).

Under normal circumstances, you can’t put your left foot on Right, or your right foot on Left. However, you CAN do a temporary “crossover”: if your left foot is on Up or Down, you can twist your hips and put your right foot on Left - but until your right foot moves away, you can’t move your left to a different arrow. (Imagine the tangle your legs would get into if you tried!) Similarly, you can cross your left foot over/behind your right.

Input

You will be given multiple arrow sequences to provide foot guides for. Every sequence consists of a line containing from 1 to 70 characters, representing the arrow that must be hit at each time unit. The possible characters are U, L, D, and R, signifying the four arrows, or a period, indicating that no arrow need be hit. Assume that your left and right feet start on the Left and Right arrows for the first time unit of a sequence.
There are at most 100 sequences. Input is terminated by a line consisting of a single #.

Output

For each input sequence, output a string of the same length, indicating which foot should perform an action at each time step, or ‘.’ if neither does. If there are multiple solutions that require minimal energy, any will do.
Sample Input

LRLRLLLLRLRLRRRRLLRRLRLDU…D…UUUUDDDD
#
Possible Output for Sample Input

LRLRLLLLRLRLRRRRLLRRLRLRL…R…LLLLRRRR

#include <iostream>
#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=100+10;

//d[i][a][b][s]表示在走第i步时左脚在a,右脚在b,上次移动的脚是s(0为不动,1为左脚,2为右脚)所花费的最少未来代价。
int d[maxn][4][4][3];
//action[i][a][b][s]具体描述该步怎么走:action[i][a][b][s]=f*4+t;f是所动的脚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;
}
int energy(int i,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;
    if(b==LEFT&&ta!=a)return -1;

    int e;
    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=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(ans>cost)
    {
        ans=cost;
        action[i][a][b][s]=f*4+t;
    }

}
int main()
{
    pos['U']=0,pos['L']=1,pos['R']=2,pos['D']=3;
    while(scanf("%s",seq)==1)
    {
        if(seq[0]=='#')break;
        int 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)
                    {
                        for(int s=0;s<3;s++)
                        {
                            d[i][a][b][s]=n*10;
                            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]]);
                            }
                        }
                    }
                }
            }
        }
        //cout<<d[0][1][2][0]//这是最少花费的能量 
        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==1)a=t;
            else if(f==2)b=t;
        }
        printf("\n");
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值