2192: Wells弹键盘
Description
Wells十分羡慕和佩服那些会弹钢琴的人比如子浩君,然而Wells只会弹键盘…… Wells的键盘只有10个键,从1,2,3,……,9,0,如下图所示:
而且作为一个正常人,Wells也有两只手,但是为了显示出自己高超的弹键盘水平,Wells决定每只手只动用一个手指,左手指和右手指,来进行按键操作,初始左右手指分别在5,6两个按键上。每一个单位时间(1s),对于一个手指,Wells可以进行如下操作之一:
- 按下位于手指位置的按键。
- 将手指向左或向右移动一格,当然不能移到键盘外面。
必须注意以下几点:
- 在任意时刻,正常人左手指都必须在右手指的左边,当然右手指就在左手指的右边。
- 在一个单位时间内,只有一个手指可以按下按键。当然,另一个手指还是可以移动的。
现在,给Wells得到一个高级键盘谱(一个仅含0~9的非空字符串)可以在梦里弹出不输于钢琴的旋律,但强迫症Wells一定要知道高级键盘谱弹奏最少要几秒才能弹完,但Wells数学太差了,所以Wells求助于你,本世纪最优秀的程序yuan之一来帮助他!
Input
输入文件有若干行,每行描述一组数据。 对于每组数据仅一行,一个数字串s。
Output
输出若干行,每行为对应输入数据的答案。
Sample Input
434 56 57
Sample Output
5 2 2
Hint
对于20%的数据,0<=length(s)<=5,且数据组数不超过3组; 对于100%的数据,0<=length(s)<=100,且数据组数不超过100组; 保证数据中间没有空行;
Source
解题思路:定义一个三维数组dp[l][r][t]:
其中,l表示左手所在位置,r表示右手所在位置,t表示当前时间,pos表示当前应弹字符的位置,也表示已弹的字符数量。
我们可以从初始状态dp[5][6][0]=0开始遍历时间,每次从当前时间的状态推导下一秒的状态,再取最优。若pos等于给定字符串长度表示已经弹完,结束枚举。对于每个已知状态而言,下一秒共有15个可能的状态能由该状态推导得出。枚举这15个状态即可得出状态转移方程。
1 #include <iostream> 2 #include<cstdio> 3 #include<set> 4 #include<queue> 5 #include<vector> 6 #include<map> 7 #include<cmath> 8 #include<cstdlib> 9 #include<algorithm> 10 #include<string> 11 #include<cstring> 12 13 using namespace std; 14 const int INF=1e9; 15 int dp[11][11][1050]; 16 int main() 17 { 18 string s; 19 int len,ans; 20 while(cin>>s){ 21 len=s.length(); 22 ans=INF; 23 memset(dp,-1,sizeof(dp)); 24 dp[5][6][0]=0; 25 for(int t=0;t<=10*len;t++){ 26 for(int l=1;l<=10;l++){ 27 for(int r=1;r<=10;r++){ 28 if(r<=l) continue; 29 if(dp[l][r][t]==len){ 30 ans=t; 31 break; 32 } 33 if(l+'0'==s[dp[l][r][t]]){ 34 dp[l][r][t+1]=max(dp[l][r][t+1],dp[l][r][t]+1); 35 if(r+1<=10) 36 dp[l][r+1][t+1]=max(dp[l][r+1][t+1],dp[l][r][t]+1); 37 if(r-1>l) 38 dp[l][r-1][t+1]=max(dp[l][r-1][t+1],dp[l][r][t]+1); 39 } 40 if(r%10+'0'==s[dp[l][r][t]]){ 41 dp[l][r][t+1]=max(dp[l][r][t+1],dp[l][r][t]+1); 42 if(l-1>=1) 43 dp[l-1][r][t+1]=max(dp[l-1][r][t+1],dp[l][r][t]+1); 44 if(l+1<r) 45 dp[l+1][r][t+1]=max(dp[l+1][r][t+1],dp[l][r][t]+1); 46 } 47 if(l+1<r+1 && r+1<=10) 48 dp[l+1][r+1][t+1]=max(dp[l+1][r+1][t+1],dp[l][r][t]); 49 if(l+1<r) 50 dp[l+1][r][t+1]=max(dp[l+1][r][t+1],dp[l][r][t]); 51 if(l+1<r-1) 52 dp[l+1][r-1][t+1]=max(dp[l+1][r-1][t+1],dp[l][r][t]); 53 54 55 if(l<r+1 && r+1<=10) 56 dp[l][r+1][t+1]=max(dp[l][r+1][t+1],dp[l][r][t]); 57 if(l<r) 58 dp[l][r][t+1]=max(dp[l][r][t+1],dp[l][r][t]); 59 if(l<r-1) 60 dp[l][r-1][t+1]=max(dp[l][r-1][t+1],dp[l][r][t]); 61 62 if(l-1<r+1 && r+1<=10 && l-1>=1) 63 dp[l-1][r+1][t+1]=max(dp[l-1][r+1][t+1],dp[l][r][t]); 64 if(l-1<r && l-1>=1) 65 dp[l-1][r][t+1]=max(dp[l-1][r][t+1],dp[l][r][t]); 66 if(l-1<r-1 && l-1>=1) 67 dp[l-1][r-1][t+1]=max(dp[l-1][r-1][t+1],dp[l][r][t]); 68 } 69 if(ans!=INF)break; 70 } 71 if(ans!=INF)break; 72 } 73 printf("%d\n",ans); 74 } 75 return 0; 76 }