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 的出法与上次不同。
-
如果第 i 次 Takahashi 出 j 赢了,即 \(j\ne z(s_i)\),则 \(f_{i,j}=\max\left \{f_{i-1,k} +1\right\}\)。
-
如果第 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;
}

浙公网安备 33010602011771号