版权声明:http://blog.csdn.net/Mitsuha_。 https://blog.csdn.net/Mitsuha_/article/details/86412671
链接:https://ac.nowcoder.com/acm/contest/328/C
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
Rabbit通过了上次boss的考核,现在她又遇到了一个问题。
Rabbit接到了K个任务,每个任务她可以自由选择用i天去完成
。刁钻的boss想让Rabbit恰好用W天完成所有任务。
已知Rabbit用i天完成一个任务能让boss获得的满意度为
(因为完成任务的质量不同),她想知道在满足boss要求的情况下能让boss获得的总满意度最大是多少。
输入描述:
第一行三个整数N,K,W。
第二行N个整数
表示用i天完成一个任务能让boss获得的满意度。
输出描述:
输出Rabbit在满足boss要求的情况下能让boss获得的总满意度最大是多少。
示例1
输入
3 3 5
6 2 4
输出
16
说明
Rabbit可以选择分别用1天,1天,3天完成这三个任务,最大满意度为6+6+4=16
备注:
思路:容易想到一个
的算法,
表示前
个任务总共花了
天去完成的最大满意度。
需要优化。
因为
的DP是一个任务一个任务去转移的,所以我们考虑用快速幂的方式进行加速。即第一次转移选择一个任务,第二次选择两个任务,第三次选择四个任务。。。以此类推,比较类似多重背包的二进制优化。
#include<bits/stdc++.h>
using namespace std;
const int MAX=4e3+10;
const int MOD=1e9+7;
const int INF=1e9+7;
typedef long long ll;
int d[2][MAX];
int res[2][MAX];
int a[MAX];
int main()
{
int n,m,w;
cin>>n>>m>>w;
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
memset(d,0,sizeof d);
for(int i=0;i<=w;i++)res[0][i]=res[1][i]=-INF;
res[0][0]=0;
d[0][0]=-INF;
for(int i=1;i<=n;i++)d[0][i]=a[i];
int now=1,pre=0;
while(m)
{
if(m&1)
{
for(int i=w;i>=0;i--)
{
res[now][i]=-INF;
for(int j=0;j<=i;j++)res[now][i]=max(res[now][i],d[pre][j]+res[pre][i-j]);
}
}
else for(int i=w;i>=0;i--)res[now][i]=res[pre][i];
for(int i=w;i>=0;i--)
{
d[now][i]=-INF;
for(int j=0;j<=i;j++)d[now][i]=max(d[now][i],d[pre][j]+d[pre][i-j]);
}
m/=2;
pre^=1;
now^=1;
}
cout<<res[pre][w]<<endl;
return 0;
}