UVa 12484 Cards

部署运行你感兴趣的模型镜像

题目描述

Alberto\texttt{Alberto}AlbertoWanderley\texttt{Wanderley}Wanderley 玩一个卡牌游戏。桌上有 NNN 张牌(NNN 为偶数),每张牌上有一个整数,排成一列。两人轮流取牌,Alberto\texttt{Alberto}Alberto 先手,每次只能从当前序列的两端(最左或最右)取一张牌,直到所有牌被取完。玩家的得分是他取到的牌上数字之和。Alberto\texttt{Alberto}Alberto 希望最大化自己的得分,Wanderley\texttt{Wanderley}Wanderley 则希望最小化 Alberto\texttt{Alberto}Alberto 的得分。两人都采取最优策略。给定牌的序列,求 Alberto\texttt{Alberto}Alberto 能获得的最大分数。

输入格式

  • 多个测试用例
  • 每个测试用例两行:
    • 第一行:整数 NNN(牌的数量)
    • 第二行:NNN 个整数,表示牌上的数字

输出格式

  • 每个测试用例一行,输出 Alberto\texttt{Alberto}Alberto 能得到的最大分数

限制条件

  • 2≤N≤1042 \leq N \leq 10^42N104
  • NNN 是偶数
  • 每个整数可以用 323232 位有符号整数表示

题目分析

这是一个典型的零和博弈问题,具有以下特点:

  1. 回合交替Alberto\texttt{Alberto}Alberto 先手,Wanderley\texttt{Wanderley}Wanderley 后手,两人轮流取牌
  2. 有限选择:每回合只能从当前序列的两端取牌
  3. 完全信息:双方都知道所有牌的数字
  4. 最优策略:双方都采取对自己最有利的策略

由于 NNN 最大可达 10410^4104,我们需要一个高效的算法来解决这个问题。

解题思路

动态规划定义

我们使用动态规划来解决这个问题。定义状态:

  • dp[i][j]dp[i][j]dp[i][j] 表示当牌堆剩下第 iii 张到第 jjj 张牌时,当前轮到的人能比对手多得的分数(当前玩家分数 −- 对手分数)

状态转移

关键点在于判断当前是谁的回合。由于初始时 NNN 是偶数且 Alberto\texttt{Alberto}Alberto 先手:

  • 当剩余牌数 (j−i+1)(j-i+1)(ji+1)偶数时,是 Alberto\texttt{Alberto}Alberto 的回合
  • 当剩余牌数 (j−i+1)(j-i+1)(ji+1)奇数时,是 Wanderley\texttt{Wanderley}Wanderley 的回合

状态转移方程

  1. Alberto\texttt{Alberto}Alberto 的回合(最大化自己的优势):
    dp[i][j]=max⁡(cards[i]+dp[i+1][j], cards[j]+dp[i][j−1]) dp[i][j] = \max(cards[i] + dp[i+1][j],\ cards[j] + dp[i][j-1]) dp[i][j]=max(cards[i]+dp[i+1][j], cards[j]+dp[i][j1])

  2. Wanderley\texttt{Wanderley}Wanderley 的回合(最小化 Alberto\texttt{Alberto}Alberto 的优势):
    dp[i][j]=min⁡(−cards[i]+dp[i+1][j], −cards[j]+dp[i][j−1]) dp[i][j] = \min(-cards[i] + dp[i+1][j],\ -cards[j] + dp[i][j-1]) dp[i][j]=min(cards[i]+dp[i+1][j], cards[j]+dp[i][j1])

空间优化

由于 NNN 最大为 10410^4104,二维 DP\texttt{DP}DP 数组需要约 10810^8108 个元素,可能超出内存限制。我们可以优化为一维 DP\texttt{DP}DP

  • 使用 dp[i]dp[i]dp[i] 表示从位置 iii 开始,当前长度为 lenlenlen 的区间中,当前玩家能比对手多得的最大分数差
  • 按区间长度从小到大计算

最终得分计算

设总分为 total=∑k=0N−1cards[k]total = \sum_{k=0}^{N-1} cards[k]total=k=0N1cards[k],最终 dp[0]dp[0]dp[0] 表示 Alberto\texttt{Alberto}AlbertoWanderley\texttt{Wanderley}Wanderley 多得的分数。那么:

  • Alberto\texttt{Alberto}Alberto 得分 AAAWanderley\texttt{Wanderley}Wanderley 得分 BBB
  • A+B=totalA + B = totalA+B=total
  • A−B=dp[0]A - B = dp[0]AB=dp[0]

解得:
A=total+dp[0]2 A = \frac{total + dp[0]}{2} A=2total+dp[0]

算法复杂度

  • 时间复杂度O(N2)O(N^2)O(N2)
  • 空间复杂度O(N)O(N)O(N)

对于 N=104N = 10^4N=104,时间复杂度为 10810^8108 级别,在现代计算机上可以接受。

代码实现

// Cards
// UVa ID: 12484
// Verdict: Accepted
// Submission Date: 2025-11-16
// UVa Run Time: 0.150s
//
// 版权所有(C)2025,邱秋。metaphysis # yeah dot net

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n;
    while (cin >> n) {
        vector<int> cards(n);
        for (int i = 0; i < n; i++)
            cin >> cards[i];
        
        vector<long long> dp(n, 0);
        
        for (int len = 1; len <= n; len++)
            for (int i = 0; i + len - 1 < n; i++) {
                int j = i + len - 1;
                if ((n - len) % 2 == 0)
                    // Alberto's turn - maximize
                    if (len == 1)
                        dp[i] = cards[i];
                    else
                        dp[i] = max(cards[i] + dp[i+1], cards[j] + dp[i]);
                else
                    // Wanderley's turn - minimize Alberto's score
                    if (len == 1)
                        dp[i] = -cards[i];
                    else
                        dp[i] = min(-cards[i] + dp[i+1], -cards[j] + dp[i]);
            }
        
        long long total = 0;
        for (int x : cards) total += x;
        long long $\texttt{Alberto}$Score = (total + dp[0]) / 2;
        cout << $\texttt{Alberto}$Score << endl;
    }
    return 0;
}

总结

本题通过动态规划巧妙地模拟了双人博弈过程,关键点在于:

  1. 正确识别当前回合的玩家
  2. Alberto\texttt{Alberto}Alberto 采取最大化策略,Wanderley\texttt{Wanderley}Wanderley 采取最小化策略
  3. 使用空间优化避免内存溢出
  4. 最终通过总分和分数差计算 Alberto\texttt{Alberto}Alberto 的实际得分

这种"当前玩家相对于对手的分数差"的思路是解决零和博弈问题的常用技巧,可以推广到类似的游戏中。

您可能感兴趣的与本文相关的镜像

Wan2.2-T2V-A5B

Wan2.2-T2V-A5B

文生视频
Wan2.2

Wan2.2是由通义万相开源高效文本到视频生成模型,是有​50亿参数的轻量级视频生成模型,专为快速内容创作优化。支持480P视频生成,具备优秀的时序连贯性和运动推理能力

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值