题解:P10111 [GESP202312 七级] 纸牌游戏

题目大意

给出三个序列:aabbcc
分别表示:分数,罚分以及小杨从第 11 轮至第 𝑁𝑁 轮出的牌,你从第 22 轮开始,要么继续出上一轮出的牌,要么记一次“换牌”。游戏结束时,你换了 tt 次牌,就要额外扣 b1++btb_1+…+b_t 分。

请计算出你最多能获得多少分。

解题思路

我们使用动态规划来解决。

状态:

fi,j,kf_{i,j,k}表示进行到第 ii 轮,换了 jj 次牌,牌为 kk 的最大得分。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <bits/stdc++.h>
using namespace std;
int n;
int a[1001], b[1001], c[1001];
int f[1001][1001][5]; // 进行到第i轮,换了j次牌,牌k的最大得分
int ans;
int main()
{
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i];
for (int i = 1; i < n; i++)
cin >> b[i];
for (int i = 1; i <= n; i++)
cin >> c[i];
for (int i = 1; i <= n; i++)
{
for (int j = 0; j < i; j++) // 枚举本轮换牌次数(到第i轮最多换了i-1次牌)
{
for (int k = 0; k < 3; k++)
{
int add = 0, hp = INT_MIN;
if ((c[i] + 1) % 3 == k)
add = a[i] * 2;
if (k == c[i])
add = a[i];
if (j < i - 1 || i == 1)
hp = max(hp, f[i - 1][j][k]);
if (j > 0)
hp = max(hp, max(f[i - 1][j - 1][(k + 1) % 3], f[i - 1][j - 1][(k + 2) % 3]) - b[j]);
f[i][j][k] = hp + add;
}
}
}
for (int i = 0; i < n; i++)
ans = max({ans, f[n][i][0], f[n][i][1], f[n][i][2]});
cout << ans;
return 0;
}