AtCoder [ABC365D] AtCoder Janken 3 题解

原文发布时间:2024-08-04 10:51。

题意:Aoki 和 Takahashi 玩石头剪刀布,给出 Aoki 的出法,求Takahashi在不能连续两次使用相同出法且不能输的情况下,最多能赢几局。

一眼 dp。

考虑设置状态,\(f_{i,j}\) 表示第 i 次石头剪刀布 Takahashi 出 j 能满足条件的赢局数的最大值。为方便写代码,用函数 z 将 R 转为 1,P 转为 2,S 转为 3。

接下来考虑状态转移:

假设第 i 次 Takahashi 出 j。

以下的 \(k\)\(k\in\left [ 1,3 \right ] \wedge k \ne ((z(s_i)-2)\bmod 3) + 1 \wedge k \ne j\)

其中\(k \ne ((z(s_i)-2)\bmod 3) + 1\)是为了保证 Takahashi 不输,\(k \ne j\) 是为了保证这次 Takahashi 的出法与上次不同。

  1. 如果第 i 次 Takahashi 出 j 赢了,即 \(j\ne z(s_i)\),则 \(f_{i,j}=\max\left \{f_{i-1,k} +1\right\}\)

  2. 如果第 i 次 Takahashi 出 j 平了,即 \(j=z(s_i)\),则 \(f_{i,j}=\max\left \{f_{i-1,k}\right\}\)

综上:
\(f_{i,j}=\max\left \{f_{i-1,k} + \left [ j \ne z(s_i) \right ] \right\}\)

最后答案即为 \(\max\left \{ f_{n,1},f_{n,2},f_{n,3} \right \}\)

代码:

#include <bits/stdc++.h>

using namespace std;

#define int long long

int f[200005][5];

string s;

int z(char a) {//字符转数字
	if (a == 'R') return 1;
	if (a == 'P') return 2;
	return 3;
}

signed main() {
	int n;
	cin >> n;
	cin >> s;
	s = " " + s;
	for (int i = 1; i <= n; i++) {
		int dc = z(s[i]);
		int bnc = ((dc - 2) % 3) + 1;//不能出
		if (bnc == 0) bnc = 3;
		for (int j = 1; j <= 3; j++) {//枚举每一种出法
			if (j != bnc) {//不会输
				for (int k = 1; k <= 3; k++) {
					if (k != j) {//不能出和上一次相同的
						if (j == dc) f[i][j] = max(f[i][j], f[i - 1][k]);//平局
						else f[i][j] = max(f[i][j], f[i - 1][k] + 1);//赢
					}
				}
			}
		}
	}
	cout << max(max(f[n][1], f[n][2]), f[n][3]) << endl;
	return 0;
}

posted @ 2025-02-10 17:05  wwqwq  阅读(35)  评论(0)    收藏  举报