SOJ2818: QQ音速题解动态规划DP

2818: QQ音速

Submit your solution     Discuss this problem     Best solutions
 

 

Description

最近flymouse开始玩qq音速,这个游戏只需要按4个键,上,下,左,右(分别用u,d,l,r表示)。 flymouse必须按照游戏规则,依次按下一系列键。问题是flymouse的手太胖了,他只能把两个手指放在方向键上。 flymouse把一个手指从键i移动到键j,要耗费w[i][j]的体力,而按键不需要耗费体力。 由于flymouse反应比较慢,所以他每次只能移动一个手指。现在可怜的flymouse问你,他最少耗费多少体力? 假设flymouse一开始就把手指放在左、右两个键上。 下面是w[i][j]数组 u d l r u 0 1 2 2 d 1 0 1 1 l 2 1 0 2 r 2 1 2 0

Input

本题有多组测试数据,请处理到EOF 每组数据仅一行,为一个仅由0,1,2,3组成的串,表示flymouse需要依次按下的键 串的长度不超过10^6 0,1,2,3 分别代表 u,d,l,r

Output

对每组输入,输出flymouse耗费的最少体力

Sample Input

01230123

Sample Output

8

Source

Felicia @ WHU
 
同黑书上的舞蹈家
状态:
 d[i][j]表示第i次按键停留在j键上的最小体力耗费
状态转移方程:
d[i][j]=d[i-1][j]+w[s[i-1]][s[i]]	(j!=s[i-1])
d[i][j]=min{d[i-1][k]+w[k][s[i]]}	(j==s[i-1],0<=k<4)
边界:
d[0][2]=w[3][s[0]]
d[0][3]=w[2][s[0]]
也可贪心,考虑到第i次按键后应停留在s[i]键上最优,
所以只需要记录每次按键后,两个手指最优停留位置
DP
//DP代码是别人的
#include<iostream>
#include<cstdlib>
#include<cstring>
using namespace std;
char a[1000001];
int d[1000001][4];
int w[4][4]={0,1, 2, 2 , 1 ,0 ,1, 1 , 2, 1 ,0 ,2 , 2 ,1 ,2 ,0}; 
int answer;
int main()
{
    int len,i,j,s;
    while(scanf("%s",a)==1)
    {
      len=strlen(a);
      memset(d,10,sizeof(d));
      for(i=0;i<4;i++)
      {
        if(i==2)
         d[0][i]=w[3][a[0]-'0'];
        else if(i==3)
         d[0][i]=w[2][a[0]-'0'];
      
      }
      for(i=1;i<len;i++)
        for(j=0;j<4;j++)
        {
           if(j!=a[i-1]-'0')
           {
              d[i][j]=d[i-1][j]+w[a[i-1]-'0'][a[i]-'0'];
           }
           else 
           {
              for(s=0;s<4;s++)
              {
                 if(d[i-1][s]+w[s][a[i]-'0']<d[i][j])
                   d[i][j]=d[i-1][s]+w[s][a[i]-'0'];
              }
           }
        }
        answer=10000000;
        for(i=0;i<4;i++)
        {
           if(d[len-1][i]<answer)
             answer=d[len-1][i];
        }
        printf("%d/n",answer);
    }
    return 0;
}
 
贪心
#include<cstdio>

int w[4][4]={0,1,2,2,1,0,1,1,2,1,0,2,2,1,2,0};
char s[1000005];
int main()
{
	while(scanf("%s",s)==1)
	{
		int i,j,t,a=2,b=3,ans=0;		
		for(i=0;s[i];i++)		
			{
				t=s[i]-48;//第i个按键
				if(w[a][t]<w[b][t])//a转换到t最优
				{
					ans+=w[a][t];
					a=t;
				}
				else if(w[a][t]>w[b][t])//b转换到t最优
				{
					ans+=w[b][t];
					b=t;
				}
				else//相同
				{
					for(j=i+1;s[j];j++)
						if(s[j]-48==a||s[j]-48==b)
							break;
					if(s[j]-48==b)//后面有b,保留b,把a转换到t
					{
						ans+=w[a][t];
						a=t;
					}
					else
					{
						ans+=w[b][t];
						b=t;
					}
				}
			}		
		printf("%d/n",ans);	
	}
}
 

你可能感兴趣的:(游戏,qq,测试,input,output)