COJ 2192: Wells弹键盘 (dp)
2192: Wells彈鍵盤
Description
Wells十分羨慕和佩服那些會彈鋼琴的人比如子浩君,然而Wells只會彈鍵盤…… Wells的鍵盤只有10個鍵,從1,2,3,……,9,0,如下圖所示:
而且作為一個正常人,Wells也有兩只手,但是為了顯示出自己高超的彈鍵盤水平,Wells決定每只手只動用一個手指,左手指和右手指,來進行按鍵操作,初始左右手指分別在5,6兩個按鍵上。每一個單位時間(1s),對于一個手指,Wells可以進行如下操作之一:
- 按下位于手指位置的按鍵。
- 將手指向左或向右移動一格,當(dāng)然不能移到鍵盤外面。
必須注意以下幾點:
- 在任意時刻,正常人左手指都必須在右手指的左邊,當(dāng)然右手指就在左手指的右邊。
- 在一個單位時間內(nèi),只有一個手指可以按下按鍵。當(dāng)然,另一個手指還是可以移動的。
現(xiàn)在,給Wells得到一個高級鍵盤譜(一個僅含0~9的非空字符串)可以在夢里彈出不輸于鋼琴的旋律,但強迫癥Wells一定要知道高級鍵盤譜彈奏最少要幾秒才能彈完,但Wells數(shù)學(xué)太差了,所以Wells求助于你,本世紀最優(yōu)秀的程序yuan之一來幫助他!
Input
輸入文件有若干行,每行描述一組數(shù)據(jù)。 對于每組數(shù)據(jù)僅一行,一個數(shù)字串s。
Output
輸出若干行,每行為對應(yīng)輸入數(shù)據(jù)的答案。
Sample Input
434 56 57Sample Output
5 2 2Hint
對于20%的數(shù)據(jù),0<=length(s)<=5,且數(shù)據(jù)組數(shù)不超過3組; 對于100%的數(shù)據(jù),0<=length(s)<=100,且數(shù)據(jù)組數(shù)不超過100組; 保證數(shù)據(jù)中間沒有空行;
Source
?
解題思路:定義一個三維數(shù)組dp[l][r][t]:
其中,l表示左手所在位置,r表示右手所在位置,t表示當(dāng)前時間,pos表示當(dāng)前應(yīng)彈字符的位置,也表示已彈的字符數(shù)量。
??? 我們可以從初始狀態(tài)dp[5][6][0]=0開始遍歷時間,每次從當(dāng)前時間的狀態(tài)推導(dǎo)下一秒的狀態(tài),再取最優(yōu)。若pos等于給定字符串長度表示已經(jīng)彈完,結(jié)束枚舉。對于每個已知狀態(tài)而言,下一秒共有15個可能的狀態(tài)能由該狀態(tài)推導(dǎo)得出。枚舉這15個狀態(tài)即可得出狀態(tài)轉(zhuǎn)移方程。
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 } View Code?
?
轉(zhuǎn)載于:https://www.cnblogs.com/zengzk/p/10076817.html
總結(jié)
以上是生活随笔為你收集整理的COJ 2192: Wells弹键盘 (dp)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hello word 程序 ——简单的s
- 下一篇: go 字符串拼接