题目背景

对应的选择、判断题:试题 - GESP 202312 C++ 七级 - 洛谷有题

题目描述

你和小杨在玩一个纸牌游戏。

你和小杨各有 3 张牌,分别是 0、1、2。你们要进行 N 轮游戏,每轮游戏双方都要出一张牌,并按 1 战胜 0,2 战胜 1,0 战胜 2 的规则决出胜负。第 i 轮的胜者可以获得 2×ai​ 分,败者不得分,如果双方出牌相同,则算平局,二人都可获得 ai​ 分 (i=1,2,⋯,N)。

玩了一会后,你们觉得这样太过于单调,于是双方给自己制定了不同的新规则。小杨会在整局游戏开始前确定自己全部 n 轮的出牌,并将他的全部计划告诉你;而你从第 2 轮开始,要么继续出上一轮出的牌,要么记一次“换牌”。游戏结束时,你换了 t 次牌,就要额外扣 b1​+⋯+bt​ 分。

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

输入格式

第一行一个整数 N,表示游戏轮数。

第二行 N 个用单个空格隔开的非负整数 a1​,⋯,aN​,意义见题目描述。

第三行 N−1 个用单个空格隔开的非负整数 b1​,⋯,bN−1​,表示换牌的罚分,具体含义见题目描述。由于游戏进行 N 轮,所以你至多可以换 N−1 次牌。

第四行 N 个用单个空格隔开的整数 c1​,⋯,cN​,依次表示小杨从第 1 轮至第 N 轮出的牌。保证 ci​∈{0,1,2}。

输出格式

一行一个整数,表示你最多获得的分数。

输入输出样例

输入 #1复制

4
1 2 10 100
1 100 1
1 1 2 0

输出 #1复制

219

输入 #2复制

6
3 7 2 8 9 4
1 3 9 27 81
0 1 2 1 2 0

输出 #2复制

56

说明/提示

样例解释 1

你可以第 1 轮出 0,并在第 2,3 轮保持不变,如此输掉第 1,2 轮,但在第 3 轮中取胜,获得 2×10=20 分;

随后,你可以在第 4 轮中以扣 1 分为代价改出 1 ,并在第 4 轮中取得胜利,获得 2×100=200 分。

如此,你可以获得最高的总分 20+200−1=219。

数据范围

对于 30% 的测试点,保证 N≤15。

对于 60% 的测试点,保证 N≤100。

对于所有测试点,保证 N≤1,000;保证 0≤ai​,bi​≤106。

代码实现:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll INF = 1e18;

int get_gain(int me, int opp, int ai)
{
    if(me == opp) return ai;
    if((me == 1 && opp == 0) || (me == 2 && opp == 1) || (me == 0 && opp == 2))
        return 2 * ai;
    return 0;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int N;
    cin >> N;
    vector<int> a(N + 1);
    for(int i = 1; i <= N; i++) cin >> a[i];
    vector<int> b(N);
    for(int i = 1; i <= N - 1; i++) cin >> b[i];
    vector<int> c(N + 1);
    for(int i = 1; i <= N; i++) cin >> c[i];

    vector<vector<vector<ll>>> dp(N + 1, vector<vector<ll>>(N, vector<ll>(3, -INF)));
    for(int x = 0; x < 3; x++)
        dp[1][0][x] = get_gain(x, c[1], a[1]);

    for(int i = 2; i <= N; i++)
    {
        for(int t = 0; t <= i - 1; t++)
        {
            for(int x = 0; x < 3; x++)
            {
                if(dp[i-1][t][x] != -INF)
                    dp[i][t][x] = max(dp[i][t][x], dp[i-1][t][x] + get_gain(x, c[i], a[i]));
                if(t >= 1)
                {
                    for(int y = 0; y < 3; y++)
                    {
                        if(y == x) continue;
                        if(dp[i-1][t-1][y] != -INF)
                        {
                            ll val = dp[i-1][t-1][y] + get_gain(x, c[i], a[i]) - b[t];
                            dp[i][t][x] = max(dp[i][t][x], val);
                        }
                    }
                }
            }
        }
    }
    ll ans = -INF;
    for(int t = 0; t <= N - 1; t++)
        for(int x = 0; x < 3; x++)
            ans = max(ans, dp[N][t][x]);
    cout << ans << endl;
    return 0;
}

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐