zoukankan      html  css  js  c++  java
  • Uva 10891 经典博弈区间DP

    经典博弈区间DP

    题目链接:https://uva.onlinejudge.org/external/108/p10891.pdf

    题意:

    给定n个数字,A和B可以从这串数字的两端任意选数字,一次只能从一端选取。

    并且A B都尽力使自己选择的结果为最大的,可以理解成A B每一步走的都是最优的。

    如果A先选择,则A B差值最大是多少。

    分析:

    总和是一定的,所以一个得分越高,另一个人的得分越低。当前状态总是最开始的状态的一个子状态。

    d(i,j): 先手取 i ~ j 最优策略下,得分最大值。

    d(i,j) = sum(i,j) - min(d(i+1,j),d(i+2,j),...,d(j,j),  d(i,j-1),d(i,j-2),...,d(i,i),0)

    0表示全部取完;

    答案就是 d(1,n) - ( sum(1,n) - d(1,n) );

    tip: sum(i,j) 可以在 O(1) 的时间内求出来。 S[i] 是 1~ i 的和,那么 sum(i,j) = S[j] - S[i-1];

    #include <bits/stdc++.h>
    
    using namespace std;
    
    int n;
    const int maxn = 100 + 10;
    
    int S[maxn],A[maxn],d[maxn][maxn],vis[maxn][maxn];
    
    int dp(int i,int j) {
        if(vis[i][j])
            return d[i][j];
        vis[i][j] = 1;
    
        int m = 0;
        for(int k=i+1;k<=j;k++)
            m = min(m,dp(k,j));
        for(int k=i;k<j;k++)
            m = min(m,dp(i,k));
    
        d[i][j] = S[j] - S[i-1] - m;
        return d[i][j];
    
    }
    
    int main()
    {
        while(scanf("%d",&n)==1&&n) {
            S[0] = 0;
            for(int i=1;i<=n;i++) {
                scanf("%d",&A[i]);
                S[i] = S[i-1] + A[i];
            }
            memset(vis,0,sizeof(vis));
            printf("%d
    ",2*dp(1,n)-S[n]);
        }
        return 0;
    }
  • 相关阅读:
    js学习(4) 函数
    Js学习(3) 数组
    NGUI的UILabel
    unity模型部分替换
    工作流程
    unity 资源内存管理
    unity 跑酷demo
    unity动画相关
    unity之C#回调函数
    maya导入unity
  • 原文地址:https://www.cnblogs.com/TreeDream/p/6129453.html
Copyright © 2011-2022 走看看