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;
}

 

posted @ 2010-09-21 10:29  勇泽  阅读(216)  评论(0编辑  收藏  举报