【codechef】Coffee Breaks(dp,剪枝)

本文介绍了一个关于程序员如何通过合理安排喝咖啡的时间来最大化代码产出的算法问题。问题旨在找到在固定数量咖啡的情况下,如何安排喝咖啡的时间点,使得编写代码的效率最高。文章提供了完整的代码实现,并附带了样例输入输出。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

像所有其他程序员一样,Sergey 非常喜欢喝咖啡,于是他每天喝恰好 K 杯咖啡。
Sergey 的一天被分成 N 段。对于每段时间,他知道自己可以写多少 KB 代码。
对于每段时间,Sergey 可以选择是否喝一杯咖啡。如果他在某段时间喝了一杯咖啡,则
他在该段时间不写任何代码,但他可以获得状态加成——如果他在某段时间选择不喝咖啡,
而上一次喝咖啡的时间距离现在不超过 D 段,则在该段时间内他可以写出正常情况下 M 倍
的代码。
作为他的生产力顾问(你的新职位!),请帮助 Sergey 规划他一天喝咖啡的时间,使他在
喝了恰好 K 杯咖啡的前提下写出最多的代码。


输入格式
输入数据第一行包含一个整数 T ,表示数据组数。接下来是 T 组数据。
每组数据第一行包含四个整数 N; K; D 和 M 。
接下来的一行包含 N 个整数 A1; A
2; : : : ; A
N ,表示 Sergey 每段时间写代码的 KB 数。

输出格式
对于每组数据,输出 Sergey 在喝了恰好 K 杯咖啡的前提下写出最多的代码的 KB 数。
数据范围
• 1 M; Ai 1000


样例数据
输入
1
5 2 2 10
1 2 3 4 5

输出
110


样例解释
第一组样例,Sergey 在第 1 段和第 3 段喝咖啡。在这两段时间里他不写任何代码,但在
其余的时间里他的写的代码量将乘 10,故总的代码量为 (2 + 4 + 5) 10 = 110KB。

https://www.codechef.com/LTIME28/problems/COFFEE

#include <bits/stdc++.h>
#define pb push_back
#define sqr(x) (x)*(x)
#define sz(a) int(a.size())
#define reset(a,b) memset(a,b,sizeof(a))
#define oo 1000000007
 
using namespace std;
 
typedef pair<int,int> pii;
typedef long long ll;
 
const int maxn=5007;
 
int n,m,k,d,a[maxn];
ll dp[maxn][maxn],s[maxn];
int myq[maxn];
 
int main(){
//    freopen("input.txt","r",stdin);
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d%d%d",&n,&k,&d,&m);
 
        for(int i=1; i<=n; ++i){
            scanf("%d",&a[i]);
            s[i]=s[i-1]+a[i];
            dp[0][i]=s[i];
        }
        for(int i=1; i<=k; ++i){
            int first=1, last=0;
            for(int p=i; p<=n; ++p){
                while(first<=last && p-myq[first]>d) ++first;
                while(first<=last && dp[i-1][myq[last]-1] - s[myq[last]]*m <= dp[i-1][p-1] - s[p]*m) --last;
                myq[++last]=p;
                dp[i][p] = (s[p] - s[myq[first]])*m + dp[i-1][myq[first]-1];
                if(p>i) dp[i][p] = max(dp[i][p], a[p] + dp[i][p-1]);
            }
        }
        printf("%lld\n",dp[k][n]);
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值