每日一题:5.8 --?

5.8:Hoof, Paper, Scissor G(蹄子,剪刀,布)
在这里插入图片描述

思路:动态规划
状态设计:
F [ i ] [ j ] [ k ] 表示第i轮,变换了j次手势,且最后一次出的是k

状态计算:
首先,如果下一轮的出拳和和上一轮一样的话,也就是不用边
f[i][j][k] = f[i - 1][j][k]
如果变的话,设上一轮出拳是x(x与k不相同)
f[i][j][k] = f[i - 1][j - 1][x]

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<sstream>
#include<map>
#include<set>
#include<stack>
#include<queue>
#include<string>
#include<vector>
#include<algorithm>
#define ll long long
#define ull unsigned long long
#define mem(a) memset(a,0,sizeof(a))
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define inf 0x3f3f3f3f
#define sf(n) scanf("%d", &n)
#define endl '\n'
#define cyes cout<<"yes"<<endl
#define debug(x) cout<<"-----"<<x<<endl

using namespace std;

const int N = 1e5 + 5;

int n, m;
int f[N][25][4];

int get() //字母转换为数字 
{
	char ch; cin >> ch;
	if(ch == 'H')	return 0; //石头 
	if(ch == 'S')	return 1; //剪刀 
	if(ch == 'P')	return 2; //布 
}

int check(int a, int b) //检查a是否能赢b 
{
	return (a + 1) % 3 == b;
}

int main()
{
	IOS;
	cin >> n >> m;
	
	for(int i = 1; i <= n; i++) //枚举第几轮 
	{
		int x = get(); //得到对手的手势 
		for(int j = 0; j <= min(i, m); j++) //枚举变换几次 
			for(int k = 0; k < 3; k++) //枚举出的手势 
			{
				f[i][j][k] = f[i - 1][j][k] + check(k, x); //不变
				if(j) //变 
				{
					int a = (k + 1) % 3;
					f[i][j][k] = max(f[i][j][k], f[i - 1][j - 1][a] + check(a, x));
					a = (a + 1) % 3;
					f[i][j][k] = max(f[i][j][k], f[i - 1][j - 1][a] + check(a, x));					
				}
			}
	}
	
	int res = 0;
	for(int j = 0; j <= m; j++) //在所有可能的情况中取一个最大值 
		for(int k = 0; k < 3; k++)
			res = max(res, f[n][j][k]);
	
	cout << res << endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值