• codevs3196 黄金宝藏


    题目描述 Description

    小毛终于到达宝藏点,他意外地发现有一个外星人(名叫Pluto)。宝藏是一些太空黄金,有n堆排成一行,每堆中有xi颗黄金。小毛和Pluto决定轮流从中取出黄金,规则是每次只能从最左边或最右边取出一堆黄金,直到所有黄金被取出。小毛先取,两人都以最优策略进行选取,求两人的最后所得。

    输入描述 Input Description

    第一行是正数n(≤500);第二行为n个正整数xi(≤300),表示每堆黄金的个数。

    输出描述 Output Description

    仅两个整数,分别表示小毛和Pluto的得分,以空格隔开。

    样例输入 Sample Input

    4 7 2 9 5 2

    样例输出 Sample Output

    18 11

     
    题解:
      设dp[i][j]表示当取到只剩下i~j的元素时的先手的最优得分,这个转移非常好像,但第一次写类似博弈的题目,写详细一些。
      首先我们有两种决策,对于区间i~j,可以取a[i],也可以取a[j],当我们取a[i]时,对手就还剩下区间i+1~j,那么此时他就变成了先手,按照最优策略取了dp[i+1][j],如果取a[j],那么还剩下区间i~j-1,那么他就会取dp[i][j-1],因为我们两个人的所取的总和是不变的,都是区间和,那么我们只有最小化他的取值,才能得到我们想要的最大得分。所以dp[i][i+len]=sum[i+len]-sum[i-1]-min(dp[i+1][i+len],dp[i][i+len-1]),因为我们是在保证后手也是用最优策略的情况下做出的判断,而转移也是用最优的转移,所以符合题意。
    代码:
    #include<iostream>
    #include<stdio.h>
    #include<cstring>
    #include<stdlib.h>
    #include<algorithm>
    #define MANX 1000
    using namespace std;
    int dp[MANX][MANX],a[MANX],sum[MANX];
    int n;
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]),sum[i]=sum[i-1]+a[i];
        for(int i=1;i<=n;i++) dp[i][i]=a[i];
        for(int len=1;len<=n-1;len++)
        for(int i=1;i+len<=n;i++)
        dp[i][i+len]=sum[i+len]-sum[i-1]-min(dp[i+1][i+len],dp[i][i+len-1]);
        printf("%d %d
    ",dp[1][n],sum[n]-dp[1][n]);
    }
  • 相关阅读:
    centos7 安装 supervisor
    远程桌面管理工具
    Delphi cxpagecontrol融合窗体
    Delphi调用网页美化SQL
    合并Dev BPL教程
    delphi 各新版本特性收集
    Delphi控件备份工具
    DBX Error: Driver could not be properly initialized..解决办法
    hugo 中文目录名 在 centos 的问题
    flutter Dialog里ListView的问题
  • 原文地址:https://www.cnblogs.com/renjianshige/p/7453834.html
Copyright © 2020-2023  润新知