每件物品有一个限制,只有当你当前现金大于qi的时候才会卖给你。
这题好好想了一下,跟之前做过的一道题有些类似。考虑简化版,有两个物品(p1,q1,v1),(p2,q2,v2),然后物品1先放的话,物品2就可以借助物品1产生的各种状态来进行下一步转移,而如果物品2的q2值过高,在这个[q2,m]的区间内都不存在物品1造成的新状态的话,那么物品1的状态就没有得到利用。而如果交换顺序,先放了物品2,那么显然物品1就可以利用物品2产生的新状态。
所以物品1能从物品2转移的状态区间其实是[min(q1+p2,m),m],物品2能从物品1转移的状态区间是[min(q2+p1,m),m]。所以尽可能地复用这个区间,让区间小的先来,区间大的后来,这样排序之后所有物品都能从前面的物品得到新状态进行转移。
而普通的01背包之所以不需要排序,是因为p1==q1,p2==q2,排序跟不排是一回事。这一类的dp题要注意后效性是否存在,如果存在通过改变顺序之类的办法来取消后效性。再有杭电上饭卡那题,qi恒定为5,所以也是需要排序的。
#include <algorithm> #include <iostream> #include <fstream> #include <sstream> #include <iomanip> #include <map> #include <set> #include <list> #include <stack> #include <queue> #include <deque> #include <vector> #include <string> #include <bitset> #include <memory> #include <complex> #include <numeric> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #include <time.h> #include <ctype.h> #include <locale.h> using namespace std; #pragma pack(4) const double eps = 1e-8; const double pi = acos(-1.0); const int inf = 0x7f7f7f7f; #define loop(a,n) \ for(int i=0;n>i;i++) \ cout<<a[i]<<(i!=n-1?' ':'\n') #define loop2(a,n,m) \ for(int i=0;n>i;i++) \ for(int j=0;m>j;j++) \ cout<<a[i][j]<<(j!=m-1?' ':'\n') #define at(a,i) ((a)&(1<<(i))) #define nt(a,i) ((a)^(1<<(i))) #define set1(a,i) ((a)|(1<<(i))) #define set0(a,i) ((a)&(~(1<<(i)))) #define cmp(a,b) (fabs((a)-(b))<eps?0:(((a)-(b))>eps?+1:-1)) #define lmax(a,b) ((a)>(b)?(a):(b)) #define lmin(a,b) ((a)<(b)?(a):(b)) #define fmax(a,b) (cmp(a,b)>0?(a):(b)) #define fmin(a,b) (cmp(a,b)<0?(a):(b)) const int MAXV = 5002; struct node { int p,q,v; bool operator < (node argu) const { return q-p>argu.q-argu.p; } }a[502]; int n,m,dp[MAXV]; int main() { #ifndef ONLINE_JUDGE freopen("Proud Merchants.txt","r",stdin); #else #endif while(scanf("%d %d",&n,&m)!=EOF) { for(int i=0;n>i;i++) { scanf("%d %d %d",&a[i].p,&a[i].q,&a[i].v); } sort(a,a+n); memset(dp,-1,sizeof(dp)); dp[m]=0; int ans=0; for(int i=0;n>i;i++) { for(int j=max(0,a[i].q-a[i].p);m>=j+a[i].p;j++) { if(dp[j+a[i].p]!=-1) { dp[j]=max(dp[j],dp[j+a[i].p]+a[i].v); ans=max(ans,dp[j]); } } } printf("%d\n",ans); } return 0; }