A simple problem--SOJ 3773
1、题目类型:DP。
2、解题思路:(1)建立DP[i][j][k]表示键盘输入第 k 个数字时的最短按键次数,此时的 i 表示the left finger的位置、j 表示the right finger 的位置;(2)DP遍历所有的情况,结束位置(即DP[i][j][len]列),寻找代价最小的情况。
3、实现方法:
#include<iostream>
#include<string>
using namespace std;
int dp[11][11][101];
int len;
string str;
void DP()
{
int i,j,k,t,s,p;
for(i=0;i<11;i++)
for(j=0;j<11;j++)
for(k=0;k<=100;k++)
dp[i][j][k]=-1;
dp[5][6][0]=0;
for(i=1;i<=len;i++)
{
t=str[i-1]-'0';
if(t==0)
t=10;
for(j=1;j<=9;j++)
{
for(k=j+1;k<=10;k++)
{
if(dp[j][k][i-1]!=-1)
{
s=t-j;//左手
if(s<0)s=-s;
s++;
for(p=k-s;p<=k+s;p++)
{
if(p<=t || p>10)
continue;
if(dp[t][p][i]==-1)
dp[t][p][i]=dp[j][k][i-1]+s;
else
dp[t][p][i]=dp[t][p][i] < dp[j][k][i-1]+s ? dp[t][p][i] : dp[j][k][i-1]+s;
}
s=t-k;//右手
if(s<0)s=-s;
s++;
for(p=j-s;p<=j+s;p++)
{
if(p>=t || p<=0)
continue;
if(dp[p][t][i]==-1)
dp[p][t][i]=dp[j][k][i-1]+s;
else
dp[p][t][i]=dp[p][t][i] < dp[j][k][i-1]+s ? dp[p][t][i] : dp[j][k][i-1]+s;
}
}
}
}
}
}
int main()
{
int i,j,ans;
while(cin>>str)
{
ans=99999999;
len=str.length();
DP();
for(i=1;i<=9;i++)
for(j=i+1;j<=10;j++)
{
if(dp[i][j][len]!=-1 && ans>dp[i][j][len])
ans=dp[i][j][len];
}
cout<<ans<<endl;
}
return 0;
}