977 AlvinZH过生日(背包DP大作战S)

977 AlvinZH过生日

思路

难题。逆推DP。

要明确dp的状态只与是否有选择权有关,而与选择权在谁手里无关。因为不论选择权在谁手里,那个人都会尽可能的获得最大的蛋糕重量。

dp[i]表示分配到第i个物品为止,当前拥有选择权的人能获得的最大蛋糕重量,即蛋糕[i~n]的最大值。以有选择权的的人列一个转移方程,然而因为我们只知道初始选择的是AlvinZH,因此我们要逆推:

dp[i] = max(dp[i+1], sum - dp[i+1] + val[i]);//max(不吃, 吃)

其中sum为[i+1~n]蛋糕总质量,最后dp[1]就是AlvinZH获得的最大价值。

注意:

  • 注释里的吃与不吃并不是一直针对同一个人的,指的是当前有选择权的人对当前蛋糕吃与不吃。
  • 整个过程没有管AlvinZH吃还是不吃,针对的对象是有选择权的那个人。

分析

这道题很有意思,巧妙地避过了选择权在谁手里的问题,dp求解的是有选择权能获得的最大价值,并没有考虑谁有选择权。

逆推也很有意思,因为只知道开始时选择权在AlvinZH手里。

好好理解吧,神奇的DP,你对它一无所知。

参考代码一

//
// Created by AlvinZH on 2017/11/5.
// Copyright (c) AlvinZH. All rights reserved.
//

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

int n;
int sum;//表示i+1~n块蛋糕的总量
int val[105], dp[105];

int main()
{
    while(~scanf("%d", &n))
    {
        sum = 0;
        memset(dp, 0, sizeof(dp));

        for(int i = 1; i <= n; ++i)
            scanf("%d", &val[i]);

        for(int i = n; i >= 1; --i)
        {
            dp[i] = max(dp[i + 1], sum - dp[i + 1] + val[i]);//max(不吃, 吃)。
            sum += val[i];
        }
        printf("%d
", dp[1]);
    }
}
原文地址:https://www.cnblogs.com/AlvinZH/p/7867597.html