P3609 [USACO17JAN] Hoof, Paper, Scissor G

题目背景

本题与 银组同名题目 在题意上一致,唯一的差别在于对变手势次数的限制。

题目描述

你可能玩过“石头,剪刀,布”,这个游戏在奶牛中同样流行,不过它的名字变成了“蹄子,剪刀,布”。

“蹄子,剪刀,布”和“石头,剪刀,布”的规则十分类似,两只奶牛数到三,然后出一个代表蹄子,剪刀或布的手势。蹄子胜过剪刀,剪刀胜过布,布胜过蹄子。特别地,如果两只奶牛的手势相同,则视为平局。

现在 FJ 和 Bassie 要进行 N 轮对抗。Bassie 已经预测了 FJ 每一轮要出的手势。然而 Bassie 很懒,她最多只想变换 K 次手势。

现在请你帮 Bassie 求出她最多能赢多少轮。

输入格式

第一行输入两个整数 N,K(1≤N≤10^5,0≤K≤20)。

接下来 N 行,每行一个字母,代表 FJ 这一轮出的手势。H 代表蹄子(Hoof),S 代表剪刀(Scissors),P 代表布(Paper)。

输出格式

输出一个整数,代表 Bassie 在最多变换 K 次手势的前提下最多赢多少轮。

输入输出样例

输入 #1

5 1
P
P
H
P
S

输出 #1

4

很简单的模拟(中间还有记忆化)

#include<bits/stdc++.h>
using namespace std;
int n,k,dp[5][100001][25],f[303030];
char s;
inline int dfs(int num,int chance,int pos){
	if(pos>n||chance>k) return 0;
	if(chance>k) return -0x3FFFFFFF;
	if(dp[num][pos][chance]!=0) return dp[num][pos][chance];
	if(chance==k){//机会用完了
		if(num==1&&f[pos]==2) dp[num][pos][chance]=dfs(1,chance,pos+1)+1;//剪刀赢了布,可以变换当前的手势,也可以不变换
		else if(num==2&&f[pos]==3) dp[num][pos][chance]=dfs(2,chance,pos+1)+1;//布赢了石头,可以变换当前的手势,也可以不变换
		else if(num==3&&f[pos]==1) dp[num][pos][chance]=dfs(3,chance,pos+1)+1;//石头赢了剪刀,可以变换当前的手势,也可以不变换
		if(num==1&&f[pos]!=2) dp[num][pos][chance]=dfs(1,chance,pos+1);//剪刀没有赢布,可以变换当前的手势,也可以不变换
		else if(num==2&&f[pos]!=3) dp[num][pos][chance]=dfs(2,chance,pos+1);//布没有赢石头,可以变换当前的手势,也可以不变换
		else if(num==3&&f[pos]!=1) dp[num][pos][chance]=dfs(3,chance,pos+1);//石头没有赢剪刀,可以变换当前的手势,也可以不变换
	}
	else{//机会没用完
		if(num==1&&f[pos]==2) dp[num][pos][chance]=max(max(dfs(1,chance,pos+1)+1,dfs(2,chance+1,pos+1)+1),dfs(3,chance+1,pos+1)+1);//剪刀赢了布,可以变换当前的手势,也可以不变换
		else if(num==2&&f[pos]==3) dp[num][pos][chance]=max(max(dfs(1,chance+1,pos+1)+1,dfs(2,chance,pos+1)+1),dfs(3,chance+1,pos+1)+1);//布赢了石头,可以变换当前的手势,也可以不变换
		else if(num==3&&f[pos]==1) dp[num][pos][chance]=max(max(dfs(1,chance+1,pos+1)+1,dfs(2,chance+1,pos+1)+1),dfs(3,chance,pos+1)+1);//石头赢了剪刀,可以变换当前的手势,也可以不变换
		if(num==1&&f[pos]!=2) dp[num][pos][chance]=max(max(dfs(1,chance,pos+1),dfs(2,chance+1,pos+1)),dfs(3,chance+1,pos+1));//剪刀没有赢布,可以变换当前的手势,也可以不变换
		else if(num==2&&f[pos]!=3) dp[num][pos][chance]=max(max(dfs(1,chance+1,pos+1),dfs(2,chance,pos+1)),dfs(3,chance+1,pos+1));//布没有赢石头,可以变换当前的手势,也可以不变换
		else if(num==3&&f[pos]!=1) dp[num][pos][chance]=max(max(dfs(1,chance+1,pos+1),dfs(2,chance+1,pos+1)),dfs(3,chance,pos+1));//石头没有赢剪刀,可以变换当前的手势,也可以不变换
	}
	return dp[num][pos][chance];
}
int main(){
	cin>>n>>k;
	for(int i=1;i<=n;++i){
		cin>>s;
		if(s=='P') f[i]=1;
		if(s=='H') f[i]=2;
		if(s=='S') f[i]=3;
	}
	cout<<max(max(dfs(1,0,1),dfs(2,0,1)),dfs(3,0,1));//模拟,一开始出剪刀||石头||布的情况 
	return 0;
}

温馨提示:记得开氧气优化欧

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值