zoukankan      html  css  js  c++  java
  • USACO / A Game (经典区间DP)

    A Game游戏

    IOI'96 - Day 1

     

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

    描述

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

    格式

    PROGRAM NAME: game1

    INPUT FORMAT:

    (file game1.in)

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

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

    OUTPUT FORMAT:

    (file game1.out)

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

    SAMPLE INPUT

    6 
    4 7 2 9 5 2
    

    SAMPLE OUTPUT

    18 11


    分析:
      简单又比较经典的区间DP,每个状态无非就是这个人从左边拿还是从右边拿嘛,然后我们看怎么表达出状态转移方程。
      子问题:假设当前状态a1,a2,a3,a4,a5,如果第一个人选最左边的,则问题转化为四个数a2,a3,a4,a5,然后第二个人先选,由于题目说第二个人方案也最优,所以选的也是最优方案;先选右边同理。
      转移方程:设f[i][j]表示选[i,j]区间的数,先选的那个人的最优方案。则:
            
          f[i][j]=Max{ sum[i+1][j]-f[i+1][j]+a[i](先选左边),sum[i][j-1]-f[i][j-1]+a[j](先选右边) }

            因为选了一个后转化成的子问题,第二个人是先选,所以第一个人只能拿到子问题的后选的人的解,即sum[i][j]-f[i][j]。


    USER: Zhipeng ZHANG [138_3531]
    TASK: game1
    LANG: C++
    
    Compiling...
    Compile: OK
    
    Executing...
       Test 1: TEST OK [0.000 secs, 3212 KB]
       Test 2: TEST OK [0.000 secs, 3212 KB]
       Test 3: TEST OK [0.000 secs, 3212 KB]
       Test 4: TEST OK [0.000 secs, 3212 KB]
       Test 5: TEST OK [0.000 secs, 3212 KB]
       Test 6: TEST OK [0.000 secs, 3212 KB]
       Test 7: TEST OK [0.000 secs, 3212 KB]
       Test 8: TEST OK [0.000 secs, 3212 KB]
       Test 9: TEST OK [0.000 secs, 3212 KB]
       Test 10: TEST OK [0.000 secs, 3212 KB]
       Test 11: TEST OK [0.000 secs, 3212 KB]
       Test 12: TEST OK [0.000 secs, 3212 KB]
       Test 13: TEST OK [0.000 secs, 3212 KB]
       Test 14: TEST OK [0.000 secs, 3212 KB]
       Test 15: TEST OK [0.000 secs, 3212 KB]
       Test 16: TEST OK [0.000 secs, 3212 KB]
    
    All tests OK.

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

     
    /*
    ID:138_3531
    LANG:C++
    TASK:game1
    */
    
    #include<fstream>
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<fstream>
    #include<queue>
    #include<climits>
    #include<vector>
    #include<map>
    #include<cmath>
    
    using namespace std;
    
    int Max(int x,int y)
    {
        return x>y?x:y;
    }
    
    int main()
    {
        freopen("game1.in","r",stdin);
        freopen("game1.out","w",stdout);
    
        int a[100];
        int f[100][100];       //
        int sum[100][100];
        memset(sum,0,sizeof(sum));
        memset(f,0,sizeof(f));
    
        int n;
        cin>>n;
    
    
        for (int i=0;i<n;i++)
            cin>>a[i];
    
        for (int i=0;i<n;i++)
            for (int j=i;j<n;j++)
                for (int k=i;k<=j;k++)
                    sum[i][j]+=a[k];
        for (int i=n-1;i>=0;i--)
            for (int j=i;j<n;j++)
            if (i==j)
                f[i][j]=a[i];
            else
                f[i][j]=Max(sum[i+1][j]-f[i+1][j]+a[i],sum[i][j-1]-f[i][j-1]+a[j]);
    
        cout<<f[0][n-1]<<" "<<sum[0][n-1]-f[0][n-1]<<endl;
    
        return 0;
    }
    
    
    
                
    举杯独醉,饮罢飞雪,茫然又一年岁。 ------AbandonZHANG
  • 相关阅读:
    获取系统当前时间
    使用键盘控制窗体的移动
    打开和关闭输入法编辑器
    屏蔽系统的Ctrl+c/x/v操作
    按Esc键实现关闭窗体
    屏蔽Alt+F4关闭窗体
    将回车键转换为Tab键
    node.js入门学习(六)--express
    curl POST如何查看响应的Header(转)
    node.js入门学习(五)--Demo模块化改造
  • 原文地址:https://www.cnblogs.com/AbandonZHANG/p/2620838.html
Copyright © 2011-2022 走看看