UVa 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

----------------------------------------------------------------------------------------------------------------------------------------------

思路:

  对于屏幕上的位置必须有一脚踩下,对两脚位置有所要求且根据脚的移动关系分配代价,求完成屏幕要求的情况下代价最小。

用状态d[i][a][b][s]表示已踩过i个命令,左右脚位置为ab,因为需要根据当前移动的脚是否刚移动过所以用s表示上次移动的脚。

状态转移方程: d[i][a][b][s]=min(d[i][ta][tb][s']+cost)

  但注意到,expr是当前的移动,移动后转移到i+1且位置成为移动后的位置, 因此需要倒序枚举i,把i+1看作是 i 的子问题

原来char[]可以这么用。

代码:

 #include<cstdio>
#include<cassert>
#include<cstring>
#define FOR(a,b,c) for(int a=(b);a<(c);a++) const int maxn = + ;
const int UP =,LEFT=,RIGHT=,DOWN=;
//const direction struct Node{
int f,t;
}; char expr[maxn],footch[]=".LR";
char pos[]; //char pos[char]=int int d[maxn][][][];
Node action[maxn][][][]; int energy(int a,int ta) {
if(a==ta) return ; //没有移动
if(a + ta == ) return ; //相对箭头 03 12
return ; //else
} 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 -;
if(ta==RIGHT && tb==LEFT) return -;
if(a==RIGHT && tb!=b) return -; //左脚在右 此时右脚不能动
if(b==LEFT && ta!=a) return -;//右脚在左 此时左脚不能动 if(f==) return ; //没有移动
else if(f != s) return ; //当前移动的脚上一次没有动
else { //动了
if(f==) return energy(a,ta); //当前动的左脚
else return energy(b,tb); //右脚
}
} void update (int i,int a,int b,int s,int f,int t) {
//状态(i,a,b,s) 将脚f移动到位置t
int ta,tb;
int v=energy(i,a,b,s,f,t,ta,tb);
if(v<) return; //移动不合法 int& ans=d[i][a][b][s];
//? : 因为s代表的是前一个移动的脚 倒叙枚举方便识别子问题
int cost=v+d[i+][ta][tb][f];
if(cost < ans) {
ans=cost;
action[i][a][b][s]=(Node){f,t};
}
} int main(){
pos['U']=; pos['L']=; pos['R']=; pos['D']=; while(scanf("%s",expr)== && expr[]!='#') {
int n=strlen(expr);
memset(d,,sizeof(d)); //为什么i要倒序枚举 ?
//state(i,a,b,s) 代表已经执行i-尾 左右脚为ab 前一次移动了s脚
for(int i=n-;i>=;i--)
FOR(a,,)
FOR(b,,) if(a!=b)
FOR(s,,) {
d[i][a][b][s]=*n;
if(expr[i]=='.'){
update(i,a,b,s,,); //不移动
FOR(t,,) { // |随便移动
update(i,a,b,s,LEFT,t);
update(i,a,b,s,RIGHT,t);
}
}
else
update(i,a,b,s,LEFT,pos[expr[i]]);
update(i,a,b,s,RIGHT,pos[expr[i]]);
} int a=LEFT,b=RIGHT,s=;
FOR(i,,n) { //output 动哪一只脚的序列
int f=action[i][a][b][s].f;
int t=action[i][a][b][s].t;
printf("%c",footch[f]);
s=f;
if(f==) a=t;
else if(f==) b=t;
//f==0 ab不动
}
printf("\n");
}
return ;
}

【暑假】[深入动态规划]UVa 10618 Tango Tango Insurrection的更多相关文章

  1. 【暑假】[深入动态规划]UVa 10618 Fun Game

    UVa 10618 Fun Game 题目: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=36035 思路:   一圈人围坐 ...

  2. 【暑假】[深入动态规划]UVa 10618 Fixing the Great Wall

    UVa 10618 Fixing the Great Wall 题目:  http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=361 ...

  3. 【Uva 10618】Tango Tango Insurrection

    [Link]: [Description] 玩跳舞机. 有一定的约束. 归纳起来就是以下三点 1.两只脚不能同时踩一个位置 2.如果左脚踩在了右键上,那么下一次移动的一定要是左脚 3.如果右脚踩在了左 ...

  4. 【暑假】[深入动态规划]UVa 10618 The Bookcase

    UVa 12099  The Bookcase 题目: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=42067 思路:    ...

  5. uva 10618 Tango Tango Insurrection 解题报告

    Tango Tango Insurrection Time Limit: 3000MS     64bit IO Format: %lld & %llu Submit Status uDebu ...

  6. 【杂题总汇】UVa-10618 Tango Tango Insurrection

    [UVa-10618] Tango Tango Insurrection ◇ 题目 +vjudge 链接+ (以下选自<算法竞赛入门经典>-刘汝佳,有删改) <题目描述> 你想 ...

  7. UVA 10618 Tango Tango Insurrection

    https://vjudge.net/problem/UVA-10618 题目 你想学着玩跳舞机.跳舞机的踏板上有4个箭头:上.下.左.右.当舞曲开始时,屏幕上会有一些箭头往上移动.当向上移动箭头与顶 ...

  8. 【暑假】[深入动态规划]UVa 1628 Pizza Delivery

    UVa 1628 Pizza Delivery 题目: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=51189 思路:    ...

  9. 【暑假】[深入动态规划]UVa 1380 A Scheduling Problem

     UVa 1380 A Scheduling Problem 题目: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=41557 ...

随机推荐

  1. The 6th Zhejiang Provincial Collegiate Programming Contest->Problem I:A Stack or A Queue?

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3210 题意:给出stack和queue的定义,一个是先进后出(FILO), ...

  2. Nagios3完整配置文档

    第一章:简单快速安装nagios 1.1 准备软件包 在做安装之前确认要对该机器拥有root权限. 确认你安装好的linux系统上已经安装如下软件包再继续. Apache GCC编译器 GD库与开发库 ...

  3. CodeForces 300A Array

    http://codeforces.com/problemset/problem/300/A 题意 :给你n个数字,让你分成3组,第一组各个数之积要小于0,第二组要大于0,第三组要等于0,符合要求的答 ...

  4. codeforces #309 div1 B

    题目啰里啰嗦说了一大堆(耐心读完题目就可以秒题了) 首先我们考虑当前置换的开头的循环节的开头 1.如果是1 1->1形成循环节 问题变成i-1的子问题 2.如果是2 1->2->1形 ...

  5. SQLite数据类型详解

    一.存储种类和数据类型: SQLite将数据值的存储划分为以下几种存储类型: 复制代码代码如下:      NULL: 表示该值为NULL值.      INTEGER: 无符号整型值.      R ...

  6. *MySQL卸载之后无法重装,卡在Apply security settings:Error Nr.1045

  7. debug类和trace类的区别

    在 .net 类库中有一个 system.diagnostics 命名空间,该命名空间提供了一些与系统进程.事件日志.和性能计数器进行交互的类库.当中包括了两个对开发人员而言十分有用的类——debug ...

  8. 使用SecureCRT上传和下载文件

    SecureCR 下的文件传输协议有ASCII .Xmodem .Ymodem .Zmodem.ASCII:这是最快的传输协议,但只能传送文本文件.Xmodem:这种传输协议速度较慢,但由于使用了CR ...

  9. C++ 类的内存分布

    C++类内存分布 转自:http://www.cnblogs.com/jerry19880126/p/3616999.html   先写下总结,通过总结下面的例子,你就会明白总结了. 下面总结一下: ...

  10. 1628. White Streaks(STL)

    1628 题意不太好理解 求横黑条 和竖黑条共有多少个 注意1*1的情况 如果横向纵向都是1*1 算为一个 否则不算 用了下vector  枚举找下 #include <iostream> ...