zoukankan      html  css  js  c++  java
  • P2964 [USACO09NOV]硬币的游戏A Coin Game (DP)

    题意:n颗硬币 两个人从前往后按顺序拿

       如果上一个人拿了i颗 那么下一个可以拿1-2*i颗

       问先手能获得的最大收益

    题解:比较典型的最大最小最大最小..DP了

       但是暴力做的话是n^3 所以就体现出了这个题的巧妙之处

       dp[i][j]表示拿到了第i颗上一个人拿了j颗

       dp[i][j]由 dp[i + k][k] k = 1,2...2 * j转移来

       dp[i][j - 1]由 dp[i + k][k] k = 1,2...2 * (j - 1)转移来

       有许多状态是一样的 所以dp[i][j-1]可以转移到dp[i][j] 再枚举两个新的状态

       显然要倒着dp

    #include <bits/stdc++.h>
    using namespace std;
    
    int sum[2005];
    int dp[2005][2005];
    
    int main()
    {
        int n;
        scanf("%d", &n);
        for(int i = 1; i <= n; i++) scanf("%d", &sum[i]), sum[i] += sum[i - 1];
    
        for(int i = i; i <= n; i++) dp[n][i] = sum[n] - sum[n - 1];
        for(int i = n - 1; i >= 1; i--)
        {
            for(int j = 1; j <= n; j++)
            {
                dp[i][j] = dp[i][j - 1];
                int k = (j - 1) * 2 + 1;
                if(i + k <= n) dp[i][j] = max(dp[i][j], sum[n] - sum[i - 1] - dp[i + k][k]);
                else dp[i][j] = max(dp[i][j], sum[n] - sum[i - 1]);
    
                k++;
                if(i + k <= n) dp[i][j] = max(dp[i][j], sum[n] - sum[i - 1] - dp[i + k][k]);
                else dp[i][j] = max(dp[i][j], sum[n] - sum[i - 1]);
            }
        }
        printf("%d
    ", dp[1][1]);
        return 0;
    }
    View Code

       

  • 相关阅读:
    hw笔试题-01
    tcp
    linux schedule
    arm架构学习
    skyeye
    RTOS
    systemdump相关
    sdio
    linux kernel 多线程
    linux内核同步
  • 原文地址:https://www.cnblogs.com/lwqq3/p/10338392.html
Copyright © 2011-2022 走看看