zoukankan      html  css  js  c++  java
  • UVA 10891 Game of Sum 区间dp

    http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=19461

    题目意思大致是给你一串数字,A,B两个人轮流从两端取一段数字并得到该串数字的和的点数,每个人都尽可能的多的点数,问A最多能比B多多少点。

    区间dp,一开始打算分AB,但是发现太麻烦了,最后用dp(l,r)表示在区间l~r中先手能赢的的最多点数。假设A是区间(l,r)的先手的话,如果A选择了(l,k )// 或(k+1,r)的数字,那他的得分(l,r)的总分减去B在余下区间作为先手能的到的分。
    即dp(l,r) = min(sum - min(dp(l,k), dp(k+1,r)));
    最终答案是A的得分减去B的得分 = 2*dp(1,n) - sum;
    ==>>预处理前缀和。

    #include <cstring>
    #include <iostream>
    using namespace std;
    
    int n;
    int a[105];
    int s[105];
    int dp[105][105];
    
    int DP(int l, int r) {
        if (dp[l][r] != -1) {
            return dp[l][r];
        }
    
        if (l == r) {
            return dp[l][r] = a[l];
        }
    
        int tmp = 0; 
        for (int k=l; k<r; k++) {
            tmp = min (tmp, DP(l, k));
            tmp = min (tmp, DP(k+1, r));
        }
    
        return dp[l][r] = s[r] - s[l-1] - tmp;
    }
    
    int main () {
        while (cin >> n) {
            if (n == 0) break;
    
            for (int i=1; i<=n; i++) {
                cin >> a[i];
            }
            memset(s, 0, sizeof s);
            for (int i=1; i<=n; i++) {
                s[i] = s[i-1] + a[i];
            }
    
            memset(dp, -1, sizeof dp);
            cout << 2 * DP(1, n) - s[n] << endl; 
        }
        return 0;
    }
    View Code
  • 相关阅读:
    idea 使用
    scala
    Java开发工具
    ActiveMQ基础
    Java 多线程实战
    Java 内部类和Lambda
    Spring 学习
    平滑重启php
    opcache
    redis的hscan命令
  • 原文地址:https://www.cnblogs.com/xuelanghu/p/4564498.html
Copyright © 2011-2022 走看看