ACM暑假训练 3426: Hoof, Paper, Scissors (三维dp动态规划)

3426: Hoof, Paper, Scissors

时间限制: 1 Sec  内存限制:128 MB
提交: 57  解决: 27
[提交][状态][讨论版]

题目描述

You have probably heard of the game "Rock, Paper, Scissors". The cows like to play a similar game they call "Hoof, Paper, Scissors". 
The rules of "Hoof, Paper, Scissors" are simple. Two cows play against each-other. They both count to three and then each simultaneously makes a gesture that represents either a hoof, a piece of paper, or a pair of scissors. Hoof beats scissors (since a hoof can smash a pair of scissors), scissors beats paper (since scissors can cut paper), and paper beats hoof (since the hoof can get a papercut). For example, if the first cow makes a "hoof" gesture and the second a "paper" gesture, then the second cow wins. Of course, it is also possible to tie, if both cows make the same gesture.

Farmer John wants to play against his prize cow, Bessie, at N games of "Hoof, Paper, Scissors" (1N100,000). Bessie, being an expert at the game, can predict each of FJ's gestures before he makes it. Unfortunately, Bessie, being a cow, is also very lazy. As a result, she tends to play the same gesture multiple times in a row. In fact, she is only willing to switch gestures at most K times over the entire set of games (0K20). For example, if K=2, she might play "hoof" for the first few games, then switch to "paper" for a while, then finish the remaining games playing "hoof".

Given the sequence of gestures FJ will be playing, please determine the maximum number of games that Bessie can win.

输入

The first line of the input file contains N and K
The remaining N lines contains FJ's gestures, each either H, P, or S.

输出

Print the maximum number of games Bessie can win, given that she can only change gestures at most K times.

样例输入

5 1
P
P
H
P
S

样例输出

4

【解析】:

dp[ i ][ j ][ t ] 表示:前i局,改变了j次,当前状态是t。


dp还是本着递推的原则,找状态方程。i肯定和i-1有关系。j和j-1有关系。t仅表示当前状态'H','P','S'.


假设现在面临第i局,且改变了j次,已是最优值。

那么当前这一局有两种情况:


1、改变一次。那么dp[ i ][ j ][ t ]=前i-1局改变j-1次的最优值+本局胜负。

dp[ i ][ j ][ t ]=max(dp[i-1][j-1][m])+ check ,m=(0,1,2)&&m!=t ;

意思是当前状态从另外两种状态改变而来,所以用另外两种状态推出当前状态

2、本局不变,用上一局的状态。那么dp[ i ][ j ][ t ]=前i-1局改变j次的最优值+本局胜负。

dp[ i ][ j ][ t ]= dp[i-1][j][t] + check

当前状态由前面的相同状态t得来。


对上面两种情况取大的,得dp[ i ][ j ][ t ]。

关于check是当前局的胜负判断,胜得1,不胜得0;


看图更清晰:蓝色箭头情况2,绿色箭头情况1。


【代码】:

#include<stdio.h>  
#include<stdlib.h>  
#include<iostream>  
#include<algorithm>  
using namespace std;  
int n,k;  
int a[202020];  
int dp[120000][30][3];  
int check(int i,int j)  
{  
    if(i-j==1||i-j==-2)return 1;  
    return 0;  
}  
int main()  
{  
    cin>>n>>k; char s[20];    
    for(int i=1;i<=n;i++){  
        cin>>s;  
        if(s[0]=='H')a[i]=0;//石头   
        if(s[0]=='P')a[i]=1;//布   
        if(s[0]=='S')a[i]=2;//剪刀   
    }  
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=k;j++)
        {
            for(int t=0;t<3;t++)
            {  
                if(!j){  
                    dp[i][j][t]=dp[i-1][j][t] + check(t,a[i]);//不换  
                    continue;  
                }  
                int yes=max(dp[i-1][j-1][(t+1)%3], dp[i-1][j-1][(t+2)%3])+check(t,a[i]);//手势换  
                int no=dp[i-1][j][t] + check(t,a[i]);//不换  
                dp[i][j][t]=max(yes,no);  
            }  
        }  
    }  
    int ans=0;
    for(int t=0;t<3;t++)  
        ans=max(ans,dp[n][k][t]);  
    cout<<ans<<endl;  
    return 0;  
}  



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雪的期许

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值