• 洛谷P2734 游戏 A Game


    P2734 游戏 A Game

      • 27通过
      • 60提交
    • 题目提供者该用户不存在
    • 标签USACO
    • 难度普及+/提高

      讨论  题解  

    最新讨论

    • 暂时没有讨论

    题目背景

    有如下一个双人游戏:N(2 <= N <= 100)个正整数的序列放在一个游戏平台上,游戏由玩家1开始,两人轮流从序列的任意一端取一个数,取数后该数字被去掉并累加到本玩家的得分中,当数取尽时,游戏结束。以最终得分多者为胜。

    题目描述

    编一个执行最优策略的程序,最优策略就是使玩家在与最好的对手对弈时,能得到的在当前情况下最大的可能的总分的策略。你的程序要始终为第二位玩家执行最优策略。

    输入输出格式

    输入格式:

    第一行: 正整数N, 表示序列中正整数的个数。

    第二行至末尾: 用空格分隔的N个正整数(大小为1-200)。

    输出格式:

    只有一行,用空格分隔的两个整数: 依次为玩家一和玩家二最终的得分。

    输入输出样例

    输入样例#1:
    6 
    4 7 2 9 5 2
    输出样例#1:
    18 11

    说明

    题目翻译来自NOCOW。

    USACO Training Section 3.3

    分析:这道题和noip2007矩阵取数游戏非常像,只需要在一个序列中取数即可,要求最大得分,很明显是dp,设f[i][j]为在序列的第i个元素到第j个元素中先手能获得的最大的分,答案显然是f[1][n],怎么转移呢?决策只有两个,要么在i取,要么在j取,那么f[i][j]和f[i+1][j]、f[i][j-1]有关系,因为状态定义的是先手,所以用当前区间的总分数-后手的分数,即f[i][j] = s[i][j] - min(f[i+1][j],f[i][j-1]),其中s是第i个元素到第j个元素的和,因为i从i+1推得,j从j-1推得,所以i逆推,j顺退.

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    int n,s[110],f[110][110],a[110];
    
    int main()
    {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++)
        {
            scanf("%d", &a[i]);
            s[i] = s[i - 1] + a[i];
            f[i][i] = a[i];
        }
        for (int i = n - 1; i >= 1; i--)
            for (int j = i + 1;j <= n; j++)
                f[i][j] = s[j] - s[i - 1] - min(f[i + 1][j], f[i][j - 1]);
        printf("%d %d
    ", f[1][n], s[n] - f[1][n]);
    
        return 0;
    }
  • 相关阅读:
    centos yum安装报错could not resolve host: mirrorlist.centos.org
    feign拦截器和解码器
    git error:invalid path
    Codeforces Round #689 (Div. 2)
    RSA加解密,Java和C#互通
    C# WinForm遍历窗体控件的3种方法
    vs2019如何自动生成有下划线前缀的字段名?
    C# EF Core 后端代码已定义的用户实体,如何扩展字段?
    SQL Server 查询分析及优化方法
    SQL Server 新增函数大全(各版本)
  • 原文地址:https://www.cnblogs.com/zbtrs/p/5958039.html
Copyright © 2020-2023  润新知