A Question of Ingestion

5028: A Question of Ingestion

时间限制: 1 Sec  内存限制: 128 MB
提交: 89  解决: 24
[提交] [状态] [讨论版] [命题人:admin]

题目描述

Stan Ford is a typical college graduate student, meaning that one of the most important things on his mind is where his next meal will be. Fortune has smiled on him as he’s been invited to a multi-course barbecue put on by some of the corporate sponsors of his research team, where each course lasts exactly one hour.Stan is a bit of an analytical type and has determined that his eating pattern over a set of consecutive hours is always very consistent. In the first hour, he can eat up to m calories (where m depends on factors such as stress, bio-rhythms, position of the planets, etc.), but that amount goes down by a factor of two-thirds each consecutive hour afterwards (always truncating in cases of fractions of a calorie). However, if he stops eating for one hour, the next hour he can eat at the same rate as he did before he stopped. So, for example, if m = 900 and he ate for five consecutive hours, the most he could eat each of those hours would be 900, 600, 400, 266 and 177 calories, respectively. If, however, he didn’t eat in the third hour, he could then eat 900, 600, 0, 600 and 400 calories in each of those hours. Furthermore, if Stan can refrain from eating for two hours, then the hour after that he’s capable of eating m calories again. In the example above, if Stan didn’t eat during the third and fourth hours, then he could consume 900, 600, 0, 0 and 900 calories.

Stan is waiting to hear what will be served each hour of the barbecue as he realizes that the menu will determine when and how often he should refrain from eating. For example, if the barbecue lasts 5 hours and the courses served each hour have calories 800, 700, 400, 300, 200 then the best strategy when m = 900 is to eat every hour for a total consumption of 800 + 600 + 400 + 266 + 177 = 2 243 calories. If however, the third course is reduced from 400 calories to 40 calories (some low-calorie celery dish), then the best strategy is to not eat during the third hour — this results in a total consumption of 1 900 calories. The prospect of all this upcoming food has got Stan so frazzled he can’t think straight. Given the number of courses and the number of calories for each course, can you determine the maximum amount of calories Stan can eat?

输入

Input starts with a line containing two positive integers n m (n ≤ 100, m ≤ 20 000) indicating the number of courses and the number of calories Stan can eat in the first hour, respectively. The next line contains n positive integers indicating the number of calories for each course.

输出

Display the maximum number of calories Stan can consume.

样例输入

5 900
800 700 400 300 200

样例输出

2243

dp题,说实话我dp题基本就没对过qwq

本来想着是dp[i]表示i点能吃到的最大值,vm[i],表示当前的食量限制,那么,

当前的dp[i]就可以从前之前所有状态转移过来,就是下面这段。。但是这并不对

vm[0] = m;
    dp[0] = a[0];
    for(int i=1;i<n;i++)
    {
        vm[i] = 2*vm[i-1]/3;
        dp[i] = dp[i-1] + min(a[i],vm[i]);
        if(i>1)
        {
            if(dp[i]<=dp[i-2]+min(a[i],vm[i-2]))
            {
                dp[i] = dp[i-2]+min(a[i],vm[i-2]);
                vm[i] = vm[i-2];
            }
            for(int j=i-3;j+1;j--)
            {
                if(dp[i]<=dp[j]+min(a[i],m))
                {
                    dp[i] = dp[j]+min(a[i],m);
                    vm[i] = m;
                }
            }
        }
        else
        {
            if(dp[i]<=min(a[i],m))
            {
                dp[i] = min(a[i],m);
                vm[i] = m;
            }
        }
    }

对于第i个点,这样少考虑了很多状态,

实际上,可以连续0,1,2,*****,i次过来,这样第i个点的来源用之前的想法就不对了

应该是开二维数组dp[i][j]来表示第i个点,j次连续的最大值

这样讨论前1,2,3,个点出过来就可以了

有点像之前的概率dp传送门

AC代码

#include<bits/stdc++.h>
using namespace std;
int dp[150][150],a[150],p[150],n,m;

int main()
{

    scanf("%d%d",&n,&m);
    p[0] = m;
    for(int i=1;i<=n;i++)p[i] = 2*p[i-1]/3;///预处理食量限制
    for(int i=0;i<n;i++)scanf("%d",&a[i]);
    for(int i=0;i<n;i++)dp[i][0] = min(m,a[i]);///对于dp赋初值

    for(int i=0;i<n;i++)
    {
        for(int j=0;j<=n;j++)
        {
            if(i+1<n)
                dp[i+1][j+1] = max(dp[i+1][j+1],dp[i][j]+min(a[i+1],p[j+1]));///向后1个点,直接走
            if(i+2<n)
                dp[i+2][j] = max(dp[i+2][j],dp[i][j]+min(a[i+2],p[j]));///向后两个点,食量限制与当前相同p[j]
            if(i+3<n)
                dp[i+3][0] = max(dp[i+3][0],dp[i][j]+min(a[i+3],m));///三个点,限制为m,并且连续次数变成0
        }
    }
    int ans = 0;
    for(int i=0;i<n;i++)
        for(int j=0;j<=n;j++)
            ans = max(ans,dp[i][j]);///在所有可能中找最大
    printf("%d\n",ans);

    return 0;
}

猜你喜欢

转载自blog.csdn.net/Du_Mingm/article/details/82353606