usaco3.3.5 A Game

本文介绍了一个两玩家博弈游戏,目标是在交替从两端移除并累加数字的过程中获得比对手更高的总分。通过动态规划方法实现了最优策略,确保了在面对最佳对手时也能获取最大利益。

一 原题

A Game
IOI'96 - Day 1

Consider the following two-player game played with a sequence of N positive integers (2 <= N <= 100) laid onto a 1 x N game board. Player 1 starts the game. The players move alternately by selecting a number from either the left or the right end of the gameboar. That number is then deleted from the board, and its value is added to the score of the player who selected it. A player wins if his sum is greater than his opponents.

Write a program that implements the optimal strategy. The optimal strategy yields maximum points when playing against the "best possible" opponent. Your program must further implement an optimal strategy for player 2.

PROGRAM NAME: game1

INPUT FORMAT

Line 1:N, the size of the board
Line 2-etc:N integers in the range (1..200) that are the contents of the game board, from left to right

SAMPLE INPUT (file game1.in)

6
4 7 2 9
5 2

OUTPUT FORMAT

Two space-separated integers on a line: the score of Player 1 followed by the score of Player 2.

SAMPLE OUTPUT (file game1.out)

18 11


二 分析

动态规划。dp[i][j]表示在区间[i, j]内先手能获得的最高分数。


三 代码

运行结果:
USER: Qi Shen [maxkibb3]
TASK: game1
LANG: C++

Compiling...
Compile: OK

Executing...
   Test 1: TEST OK [0.000 secs, 4264 KB]
   Test 2: TEST OK [0.000 secs, 4264 KB]
   Test 3: TEST OK [0.000 secs, 4264 KB]
   Test 4: TEST OK [0.000 secs, 4264 KB]
   Test 5: TEST OK [0.000 secs, 4264 KB]
   Test 6: TEST OK [0.000 secs, 4264 KB]
   Test 7: TEST OK [0.000 secs, 4264 KB]
   Test 8: TEST OK [0.000 secs, 4264 KB]
   Test 9: TEST OK [0.000 secs, 4264 KB]
   Test 10: TEST OK [0.000 secs, 4264 KB]
   Test 11: TEST OK [0.000 secs, 4264 KB]
   Test 12: TEST OK [0.000 secs, 4264 KB]
   Test 13: TEST OK [0.000 secs, 4264 KB]
   Test 14: TEST OK [0.000 secs, 4264 KB]
   Test 15: TEST OK [0.000 secs, 4264 KB]
   Test 16: TEST OK [0.000 secs, 4264 KB]

All tests OK.

Your program ('game1') produced all correct answers! This is your submission #2 for this problem. Congratulations!


AC代码:
/*
ID:maxkibb3
LANG:C++
PROG:game1
*/

#include<cstdio>
#include<algorithm>
using namespace std;

const int MAXN = 105;

int n;
int a[MAXN];
int sum[MAXN][MAXN];
int dp[MAXN][MAXN];

int main() {
    freopen("game1.in", "r", stdin);
    freopen("game1.out", "w", stdout);
    scanf("%d", &n);
    for(int i = 0; i < n; i++) {
        scanf("%d", &a[i]);
        sum[i][i] = a[i];
        dp[i][i] = a[i];
    }
    for(int i = 0; i < n; i++) {
        for(int j = i + 1; j < n; j++) {
            sum[i][j] = sum[i][j - 1];
            sum[i][j] += a[j];
        }
    }
    for(int i = 1; i < n; i++) {
        for(int j = 0; j < n - i; j++) {
            dp[j][j + i] = max(a[j] + sum[j + 1][j + i] - dp[j + 1][j + i],
                           a[j + i] + sum[j][j + i - 1] - dp[j][j + i - 1]);
        }
    }
    printf("%d %d\n", dp[0][n - 1], sum[0][n - 1] - dp[0][n - 1]);
    return 0;
}


### 问题解析 USACO 中的 Shell Game(坚果壳游戏)问题是面向初学者的一道经典题目,主要考察的是对数组操作、变量追踪以及逻辑推理能力的理解。该问题通常描述如下: 在游戏开始时,一个物品(例如鹅卵石)被放置在一个坚果壳下,而三个坚果壳分别标记为 A、B 和 C。初始情况下,物品位于某个特定的位置(如 A)。随后,会进行若干次交换操作,每次交换两个坚果壳的位置。最后,要求确定物品最终所在的位置。 #### 解题思路 - **初始化**:假设物品最初位于位置 A。 - **交换过程**:使用变量记录当前物品的位置,并根据每一步的交换更新其位置。 - **输出结果**:经过所有交换后,输出物品的最终位置。 以下是基于上述思路的 Python 实现示例: ```python # 初始位置为 A position = &#39;A&#39; # 模拟交换操作 swap_sequence = [(&#39;A&#39;, &#39;B&#39;), (&#39;B&#39;, &#39;C&#39;), (&#39;A&#39;, &#39;C&#39;)] # 示例交换序列 for swap in swap_sequence: if position == swap[0]: position = swap[1] elif position == swap[1]: position = swap[0] # 输出最终位置 print(f"Final position: {position}") ``` ### 核心实现细节 1. **输入处理**:从文件中读取交换次数和具体的交换步骤。 2. **状态更新**:通过遍历交换步骤列表,动态更新物品的位置。 3. **输出结果**:将最终物品所在的位置写入输出文件。 以下是完整的代码实现: ```python fin = open(&#39;shell.in&#39;, &#39;r&#39;) fout = open(&#39;shell.out&#39;, &#39;w&#39;) # 读取输入 lines = fin.read().splitlines() N = int(lines[0]) # 初始化位置为 &#39;a&#39; shells = [&#39;a&#39;, &#39;b&#39;, &#39;c&#39;] # 处理每一次交换 for i in range(1, N + 1): a, b, g = map(int, lines[i].split()) shells[a - 1], shells[b - 1] = shells[b - 1], shells[a - 1] # 输出猜测结果的最大值 times = {&#39;a&#39;: 0, &#39;b&#39;: 0, &#39;c&#39;: 0} times[shells[g - 1]] += 1 fout.write(f&#39;{max(times.values())}\n&#39;) # 关闭文件 fout.close() ``` ### 延伸思考 Shell Game 题目可以扩展为更复杂的变种,例如: - **多轮交换与多次查询**:允许物品多次移动并支持多次查询。 - **逆向求解**:已知最终物品位置,反推初始位置或交换顺序。 - **动态交互式问题**:用户实时输入交换步骤并立即查看结果。 这些问题的核心思想仍然围绕着状态追踪和数组操作展开。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值