【暑假】[深入动态规划]UVa 10618 Tango Tango Insurrection

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[]可以这么用。

代码:

 1 #include<cstdio>
 2 #include<cassert>
 3 #include<cstring>
 4 #define FOR(a,b,c) for(int a=(b);a<(c);a++)
 5
 6 const int maxn = 70 + 5;
 7 const int UP =0,LEFT=1,RIGHT=2,DOWN=3;
 8 //const direction
 9
10 struct Node{
11     int f,t;
12 };
13
14 char expr[maxn],footch[]=".LR";
15 char pos[256];   //char pos[char]=int
16
17 int d[maxn][4][4][3];
18 Node action[maxn][4][4][3];
19
20 int energy(int a,int ta) {
21     if(a==ta) return 3;   //没有移动
22     if(a + ta == 3) return 7;  //相对箭头 03 12
23     return 5;   //else
24 }
25
26 int energy(int i,int a,int b,int s,int f,int t,int& ta,int& tb) {
27     ta=a; tb=b;
28     if(f==LEFT) ta=t;
29     else if(f==RIGHT) tb=t;
30
31     if(ta==tb) return -1;
32     if(ta==RIGHT && tb==LEFT) return -1;
33     if(a==RIGHT && tb!=b)   return -1; //左脚在右 此时右脚不能动
34     if(b==LEFT  && ta!=a)    return -1;//右脚在左 此时左脚不能动
35
36     if(f==0) return 0;      //没有移动
37     else  if(f != s) return 1;  //当前移动的脚上一次没有动
38     else {   //动了
39         if(f==1) return energy(a,ta); //当前动的左脚
40         else return energy(b,tb);    //右脚
41     }
42 }
43
44 void update (int i,int a,int b,int s,int f,int t) {
45 //状态(i,a,b,s) 将脚f移动到位置t
46     int ta,tb;
47     int v=energy(i,a,b,s,f,t,ta,tb);
48     if(v<0) return;  //移动不合法
49
50     int& ans=d[i][a][b][s];
51     //? : 因为s代表的是前一个移动的脚 倒叙枚举方便识别子问题
52     int cost=v+d[i+1][ta][tb][f];
53     if(cost < ans) {
54         ans=cost;
55         action[i][a][b][s]=(Node){f,t};
56     }
57 }
58
59 int main(){
60     pos[‘U‘]=0; pos[‘L‘]=1; pos[‘R‘]=2; pos[‘D‘]=3;
61
62     while(scanf("%s",expr)==1 && expr[0]!=‘#‘) {
63         int n=strlen(expr);
64         memset(d,0,sizeof(d));
65
66         //为什么i要倒序枚举 ?
67         //state(i,a,b,s) 代表已经执行i-尾  左右脚为ab 前一次移动了s脚
68         for(int i=n-1;i>=0;i--)
69           FOR(a,0,4)
70             FOR(b,0,4) if(a!=b)
71               FOR(s,0,3) {
72                 d[i][a][b][s]=10*n;
73                   if(expr[i]==‘.‘){
74                       update(i,a,b,s,0,0); //不移动
75                       FOR(t,0,4) {          // |随便移动
76                           update(i,a,b,s,LEFT,t);
77                           update(i,a,b,s,RIGHT,t);
78                       }
79                   }
80                   else
81                    update(i,a,b,s,LEFT,pos[expr[i]]);
82                    update(i,a,b,s,RIGHT,pos[expr[i]]);
83               }
84
85         int a=LEFT,b=RIGHT,s=0;
86         FOR(i,0,n) {  //output 动哪一只脚的序列
87             int f=action[i][a][b][s].f;
88             int t=action[i][a][b][s].t;
89             printf("%c",footch[f]);
90             s=f;
91             if(f==1) a=t;
92             else if(f==2) b=t;
93             //f==0 ab不动
94         }
95         printf("\n");
96     }
97     return 0;
98 }
时间: 2024-11-13 15:43:50

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

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

UVa 10618 Fixing the Great Wall 题目:  http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=36139 思路:   数轴上有n个点需要修复,每个点有信息c,x,d 表示位于x且在t时修缮的费用是c+d*t,找一个修缮序列使n个点能全部修缮且有费用最小. 可以发现:在任意时刻,修缮完的点都是连续的,因为修缮不需要时间,将一些点“顺手”修缮了肯定不差. d[i][j][k],表示已经将i-j个点修缮

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

UVa 12099  The Bookcase 题目: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=42067 思路:   将n本书分配到三层,使得形成的书架w*h最小 提前将书籍按照高度排序,因为无论第一本书(最高的书)无论放在那一层都会被考虑到,所以规定将它放在第一层,且第二层比第三层高. 因为从大到小排序的关系,只要jk==0那么新加入的书i就是该层的高度,否则高度不变. 设d[i][j][k]表示考虑过i本书第二

【暑假】[深入动态规划]UVa 12170 Easy Climb

UVa 12170 Easy Climb 题目: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=24844 思路:  引别人一个题解琢磨一下: from:http://blog.csdn.net/glqac/article/details/45257659 代码: 1 #include<iostream> 2 #include<algorithm> 4 #define FOR(a,b,c) for(int a

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

UVa 1628 Pizza Delivery 题目: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=51189 思路:   本体与修缮长城一题有所相似.所以解法有相似之处. 不同之处就是本体可能会产生负情况,即送餐时间晚了客户会反过来找你要钱所以需要放弃,但修缮长城只有费用,顺手修了肯定是一个不错的选择. 依旧将区间两端与位置作为状态不过要添加一维cnt表示还需要送餐的人数.类似地定义:d[i][j][cnt][p]表示

【暑假】[深入动态规划]UVa 1627 Team them up!

UVa 1627 Team them up! 题目: Team them up! Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description Your task is to divide a number of persons into two teams, in such a way, that: everyone belongs to one of th

【暑假】[深入动态规划]UVa 1412 Fund Management

UVa 1412 Fund Management 题目: UVA - 1412 Fund Management Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description Frank is a portfolio manager of a closed-end fund for Advanced Commercial Markets (ACM ). Fund

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

 UVa 1380 A Scheduling Problem 题目: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=41557 思路:   (/▽\=) 代码: 1 // UVa1380 A Scheduling Problem 2 // Rujia Liu 3 #include<iostream> 4 #include<string> 5 #include<cstring> 6 #include

【暑假】[数学]UVa 1262 Password

UVa 1262  Password 题目: Password Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description Shoulder-surfing is the behavior of intentionally and stealthily watching the screen of another person's electronic de

【暑假】[数学]UVa 10375 Choose and divide

UVa 10375 Choose and divide 题目: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=19601 思路: maxn=10000 如果计算maxn!再保存的话显然装不下. 但答案由阶乘的积或商组成,所以可以用唯一分解定理求解.大题思路就是把目前答案的质因子的指数用数组e保存,乘除都对e操作. 需要注意的是筛法求素数优化后的写法. 代码: 1 #include<iostream> 2 #include