A Question of Ingestion

A Question of Ingestion

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 = 2243 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 1900 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

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.

Output

Display the maximum number of calories Stan can consume.

Sample Input 1
5 900
800 700 400 300 200
Sample Output 1
2243
Sample Input 2
5 900
800 700 40 300 200
Sample Output 2
1900

题解

题意:n个小时,m为刚开始可以摄取的最大的卡路里
下面n个数表示每个小时有多少卡路里
从第1个小时开始吃,每次吃完,可摄取的最大的卡路里变为原来可摄取的2/3;
若第i个小时不吃,则第i+1小时可摄取的最大卡路里是第i-1小时可摄取的最大值;
若连续两个小时不吃(第i和i+1小时不吃),则第i+2小时可摄取的卡路里变为m;
求最后获得的卡路里的最大值

有两种解决方法;

方法一:递归+记忆化搜索

#include <cstdio>
#include <iostream>
using namespace std;
const int Max=110;
const int Max1=2e4+5;
int val[Max],dp[Max][Max1];
int m,n,ans=0;
int dfs(int i,int j)
{
    if(i>n)
        return 0;
    if(dp[i][j]!=-1)
        return dp[i][j];
    dp[i][j]=min(val[i],j)+max(dfs(i+1,j*2/3),max(dfs(i+2,j),dfs(i+3,m)));
    return dp[i][j];
}
void init()
{
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
            dp[i][j]=-1;
    }
}
int main()
{
    cin >> n >> m;
    for(int i=1;i<=n;i++)
        cin >> val[i];
    init();
    for(int i=1;i<=n;i++)
        ans=max(ans,dfs(i,m));
    cout << ans << endl;
    return 0;
}

方法二:dp

#include <cstdio>
#include <iostream>
using namespace std;
const int Max=110;
int dp[Max][Max],val[Max],d[Max];
int main()
{
    int n,m,ans=0;
    cin >> n >> m;
    for(int i=1;i<=n;i++)
        cin >> val[i];
    d[1]=m;
    for(int i=2;i<=n;i++)
        d[i]=d[i-1]*2/3,dp[i][1]=min(val[i],m);
//    dp[i][j]表示在i个小时,它吃的等级为j
//    等级的意思是:在第1个小时时,等级为1;第2个小时时,等级为2;后面以此类推。因为它每次可吃的最大值在递减(2/3)^j
//    如果在第i-1小时不吃,此时等级为j,那么在第i小时的等级仍然为j,因为在第i小时时,它可吃的最大值为第i-1小时可吃的最大值
//    如果在第i-1和i-2这两个小时连续不吃,那么在第i个小时的等级为1,因为此时在第i个小时可吃的最大值为初始值
//    如果在第i个小时吃,那么它可以从第i-1小时递推来、第i-2小时递推来、从第i-3小时递推来
    for(int i=1;i<=n;i++) {
        for(int j=1;j<=i;j++) {
            if(i>=1)
                dp[i][j]=max(dp[i][j],dp[i-1][j-1]+min(val[i],d[j])); // 从第i-1小时递推来
            if(i>=2)
                dp[i][j]=max(dp[i][j],dp[i-2][j]+min(val[i],d[j])); // 第i-2小时递推来,第i-1小时不吃
            if(i>=3)
                dp[i][1]=max(dp[i][1],dp[i-3][j]+min(val[i],d[1])); // 从第i-3小时递推来,第i-1和第i-2小时不吃
            ans=max(ans,dp[i][j]);
            ans=max(ans,dp[i][1]);
        }
    }
    cout << ans << endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值