题号:NC14400
链接:https://ac.nowcoder.com/acm/problem/14400
来源:牛客网
题目描述
齐齐和司机正在玩剪刀石头布,不过他俩有些玩腻了,所以思考了一个全新的“剪刀石头布”的游戏。
全新的“剪刀石头布“”的胜负规则和剪刀石头布一样,每人有3种手势,分别为剪刀(scissors)、石头(rock)、布(paper)。剪刀胜于布,布胜于石头,石头胜于剪刀,当手势相同时为平局。
齐齐可以在司机出手势后再出自己的手势,但是不能连续两局出同一种手势。
他们一共进行n盘对局。每一盘中,胜者+1分,败者-1分,平局两人都不扣分。
已知司机的n局的出手势情况,求齐齐进行n盘对局后获得的最高分数。
思路:
典型的dp问题(动态规划)
变量参数有两个:1.进行到第i轮,2.上一轮出的是什么。
dp[i][k]:代表第i轮比赛时候出k的最高分数。
说明:0代表石头,1代表布,2代表剪刀
那么dp[i][0]=max(dp[i-1][1]+dp[i-1][2])+当前第i轮出石头的分数
dp[i][1]=max(dp[i-1][0]+dp[i-1][2])+当前第i轮出布的分数
dp[i][2]=max(dp[i-1][0]+dp[i-1][1])+当前第i轮出剪刀的分数
最后一轮,必然出三个中一个,最大分数为max(dp[i][0],dp[i][1],dp[i][2])
注:附代码开的数组为dp[2][3],而不是dp[n][3],是采用滚动数组优化空间
附代码:
// dddd.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string.h>
#include <vector>
#define MAX(x,y) ((x)>(y)?(x):(y))
using namespace std;
// 0:rock
// 1:paper
// 2:scissors
int getPoint(char opponent, char me) {
if (opponent == me) return 0;
if(opponent == 'r' && me == 'p')return 1;
if (opponent == 'p' && me == 's')return 1;
if (opponent == 's' && me == 'r')return 1;
return -1;
}
int main() {
int n;
cin >> n;
char s[111];
int dp[2][3] = {};
cin >> s;
dp[0][0] = getPoint(*s, 'r');
dp[0][1] = getPoint(*s, 'p');
dp[0][2] = getPoint(*s, 's');
for (int i = 1; i < n; i++) {
cin >> s;
dp[i & 1][0] = MAX(dp[(i - 1) & 1][1], dp[(i - 1) & 1][2]) + getPoint(*s, 'r');
dp[i & 1][1] = MAX(dp[(i - 1) & 1][0], dp[(i - 1) & 1][2]) + getPoint(*s, 'p');
dp[i & 1][2] = MAX(dp[(i - 1) & 1][0], dp[(i - 1) & 1][1]) + getPoint(*s, 's');
}
cout << MAX(MAX(dp[(n - 1) & 1][0], dp[(n - 1) & 1][1]), dp[(n - 1) & 1][2]) << endl;
}