题解
2026-06-04 20:54:03
发布于:浙江
12阅读
0回复
0点赞
大家好,我是энтджей,今天是我2026年第十六次正式发题解!
能不能点个赞
首先“简化(了吗?)”题意:
- 先告诉你 (如题意)然后求最大得分(随意简化了等于没简化)
恭喜你花了几秒钟看完了这等于没简化的简化题意
然后就是写代码
-
处理输入(read):
- 正常输入(为了后期方便,将换牌所罚的分数(数组)做前缀和)
-
核心部分(process):
- 首先可以立刻看出这题是
- 那么定义数组,根据题意(有轮数,有换牌,有手牌)定义dp:
int dp[N][N][3]; //dp[i][j][k]:进行直第i轮换了j次牌且手牌为k时的最大分数 - 定义好后,求动态转移方程
- 既然是,那必定与有关
- 推导动态转移方程要看的东西有两个 1.换没换牌 2.输赢平局
- 1.根据题目,换没换牌仅仅只有两种情况,也仅仅需要看三个判断:
- 设这是第轮,换了次牌,则:
- 设这是第轮,换了次牌,则:
- 2.根据题目,可以得出判断结果的方式(不是怎么得出的?):
- 设我出的牌为x,对方出的牌是y,则:
- 把这个函数简化成 就是这样:
if(c[i] == k) //平局 else if((c[i] + 1) % 3 == k) //赢了 else //输了
- 设我出的牌为x,对方出的牌是y,则:
- 1.根据题目,换没换牌仅仅只有两种情况,也仅仅需要看三个判断:
- 看完后可以推导出动态转移方程:
-
- 表示的是加的分数,即赢了加分, 输了加分,平局加分
- lf 全称last fraction,意为上一次的分数,换牌了则等于, 以及 表示其他两种手牌;没换牌则等于。(因为不能确定,随意有可能在这里出现两个判断都通过的情况,所以 )
-
- 推导动态转移方程要看的东西有两个 1.换没换牌 2.输赢平局
- 既然是,那必定与有关
- 最后通过枚举+完成处理
-
最后输出(write):
- 遍历所有换牌次数的可能性,即到,然后取第轮,不同手牌的最大值,然后输出
完整代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1010;
const int INF = 1e18;
int n;
int a[N];
int b[N];
int s[N];
int c[N];
int dp[N][N][3]; //dp[i][j][k]:进行直第i轮换了j次牌且手牌为k时的最大分数
void init() {
s[0] = 0;
}
void read() {
cin >> n;
for(int i = 1; i <= n; i++) {
cin >> a[i];
}
for(int i = 1; i < n; i++) {
cin >> b[i];
s[i] = s[i - 1] + b[i];
}
for(int i = 1; i <= n; i++) {
cin >> c[i];
}
}
void process() {
for(int i = 1; i <= n; i++) { //枚举轮数
for(int j = 0; j <= i; j++) { //枚举换牌次数
for(int k = 0; k <= 2; k++){ //枚举手牌
//dp[i][j][k] = max({LastFraction}) + add
int add, lf = -INF; //add为要加的分数;lf全称last fraction,意为上一次的分数
if(c[i] == k) { //平局 + a[i]分
add = a[i];
} else if((c[i] + 1) % 3 == k) { //赢了 + 2*a[i]分
add = 2 * a[i];
} else { //输了 + 0分
add = 0;
}
if(i == 1 || j < i - 1) { //没有换牌
lf = dp[i - 1][j][k];
}
if(j != 0) { //换牌
lf = max({lf, dp[i - 1][j - 1][(k + 1) % 3], dp[i - 1][j - 1][(k + 2) % 3]});
}
dp[i][j][k] = lf + add;
}
}
}
}
void write() {
int ans = -INF;
for(int j = 0; j < n; j++) {
ans = max(ans, max({dp[n][j][0], dp[n][j][1], dp[n][j][2]}) - s[j]);
}
cout << ans;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
init();
read();
process();
write();
return 0;
}
🎉完结撒花🎉
好长啊,我写了好久
这里空空如也






有帮助,赞一个