题意:有很多任务,完成任务可以获得受益,每个任务有所需时间和截至日期,不能同时做两个任务,问合理选择任务能达到的最大收益。
题解:显然01背包,把容量限制和截止日期限制取交集即可。但是要注意应该先按照截至日期从早到晚排序。因为同等容量下,把截至日期早的放后面的组合一定可以换成把截至日期放前面,反之不一定可以。所以排序后不会漏情况。
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int dp[50][10000];
struct node{
int p,l,d;
}a[55];
int cmp(node a,node b){
return a.d<b.d;
}
int n;
int imax(int a,int b){
return a>b?a:b;
}
int main()
{
int i,j;
int maxx=0;
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%d%d%d",&a[i].p,&a[i].l,&a[i].d);
maxx=imax(maxx,a[i].d);
}
int maxn=0;
sort(a+1,a+n+1,cmp);
for(i=1;i<=n;i++)dp[i][a[i].l]=a[i].p;
for(i=1;i<=n;i++){
for(j=0;j<=maxx;j++){
if(a[i].d>=j&&a[i].l<=j){
dp[i][j]=imax(dp[i-1][j-a[i].l]+a[i].p,dp[i-1][j]);
}
else if(a[i].d<j){
dp[i][j]=imax(dp[i-1][j],dp[i-1][a[i].d-a[i].l]+a[i].p);
}
else dp[i][j]=dp[i-1][j];
maxn=imax(maxn,dp[i][j]);
}
}
/* for(i=1;i<=n;i++){
for(j=0;j<=maxx;j++){
printf("%d %d:%d ",i,j,dp[i][j]);
printf("\n");
}
}*/
printf("%d\n",maxn);
return 0;
}