链接:https://ac.nowcoder.com/acm/contest/328/C
来源:牛客网
Rabbit的工作(2)
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
Rabbit通过了上次boss的考核,现在她又遇到了一个问题。
Rabbit接到了K个任务,每个任务她可以自由选择用i天去完成(1≤ i≤ N)。刁钻的boss想让Rabbit恰好用W天完成所有任务。
已知Rabbit用i天完成一个任务能让boss获得的满意度为vi(因为完成任务的质量不同),她想知道在满足boss要求的情况下能让boss获得的总满意度最大是多少。
输入描述:
第一行三个整数N,K,W。
第二行N个整数vi,vi表示用i天完成一个任务能让boss获得的满意度。
输出描述:
输出Rabbit在满足boss要求的情况下能让boss获得的总满意度最大是多少。
示例1
输入
3 3 5
6 2 4
输出
16
说明
Rabbit可以选择分别用1天,1天,3天完成这三个任务,最大满意度为6+6+4=16
备注:
2≤ N,K≤ 2000,K≤ W≤ min(4000,2*K)
0<vi≤ 10000
第一次交(明显超时):
注意恰好完成,-1标记不能完成的情况。
dp[i][j]:第i个任务在第j天完成的最大收益。
dp[i][j]=max(dp[i][j],dp[i-1][j-k]+v[k]) k:rand(1-n)。
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define mod 1000000007
#define MAXN 401
int dp[2005][4005];
int main(){
int k,n,w;
scanf("%d%d%d",&n,&k,&w);
int v[2005];
for(int i=1;i<=k;i++){
scanf("%d",&v[i]);
}
for(int i=0;i<=k;i++)
for(int j=0;j<=w;j++)
dp[i][j]=-1;
dp[0][0]=0;
for(int i=1;i<=k;i++){
for(int j=i;j<=w-k+i+1;j++){
for(int k=1;k<=n;k++){
if(j-k>=0&&dp[i-1][j-k]!=-1) dp[i][j]=max(dp[i][j],dp[i-1][j-k]+v[k]);
}
}
}
cout<<dp[k][w];
return 0;
}
第二次交(AC):
先都按一天完成,这样就可以装换为完全背包。
dp[i][j]:对完成天数为i的任务进行pick时(选0个或多个),恰好多余时间为j时能得到的最大收益。
dp[i][j]=max(dp[i][j-i+1]+v[i],dp[i-1][j]);
因为有负数所以初始化为INT_MIN
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define mod 1000000007
#define MAXN 401
int dp[2005][4005];
int main(){
int k,n,w;
scanf("%d%d%d",&n,&k,&w);
int v[2005];
scanf("%d",&v[1]);
for(int i=2;i<=n;i++){
scanf("%d",&v[i]);
v[i]=v[i]-v[1];
}
int re=v[1]*k;
w=w-k;
for(int i=0;i<=k;i++)
for(int j=0;j<=w;j++)
dp[i][j]=INT_MIN;
for(int j=1;j<=n;j++)
dp[j][0]=0;
for(int i=2;i<=n;i++){
for(int j=0;j<i-1;j++)
dp[i][j]=dp[i-1][j];
for(int j=i-1;j<=w;j++){
dp[i][j]=max(dp[i][j-i+1]+v[i],dp[i-1][j]);
}
}
printf("%d",re+dp[n][w]);
return 0;
}
第三次交(显然可以替换为一维数组dp):
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define mod 1000000007
#define MAXN 401
int dp[4005];
int main(){
int k,n,w;
scanf("%d%d%d",&n,&k,&w);
int v[2005];
scanf("%d",&v[1]);
for(int i=2;i<=n;i++){
scanf("%d",&v[i]);
v[i]=v[i]-v[1];
}
int re=v[1]*k;
w=w-k;
for(int i=0;i<=w;i++)
dp[i]=INT_MIN;
dp[0]=0;
for(int i=2;i<=n;i++){
for(int j=i-1;j<=w;j++){
dp[j]=max(dp[j-i+1]+v[i],dp[j]);
}
}
printf("%d",re+dp[w]);
return 0;
}
01背包:http://www.cnblogs.com/Kalix/p/7617856.html
完全背包:https://www.cnblogs.com/Kalix/p/7622102.html