hdu 3466 Proud Merchants
题目描述: 给定n个物品及m钱,对于每个物品有三个属性,价格p,价值v,q,如果手中的钱不足q,即使能够买得起这个物品,也不能交易,求最后能买到的物品最大价值。
分析: 带限制的01背包。最容易想到的就是要按某种方式进行排序,可以先想两个问题。
1.为什么普通的01背包可以不用排序?
因为在普通的01背包问题当中每个物品是相对独立的,也就是说取得全局最优解与物品的放入顺序无关,所以不必排序就可以直接进行dp,而在这个问题中却并非如此,由于q的存在,当某一物品放入后可能就会对后面的物品造成影响,举个例子,比如背包容量为8,有两个物品,p1=5,q1=6,v1=1,p2=2,q2=4,v2=1,这时如果选择先放入第一个物品,那么第二个就无法放入,而全局最优解是两个物品都选。
2.为什么按q-p排序?
在进行dp的时候要保证所有的状态都能考虑到,q-p就是当前物品状态不需要更新的范围,按这个范围从小到大排列就能保证在状态转移的时候不会出现状态的缺失。。。。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #define N 5010 5 #define M 510 6 using namespace std; 7 struct S{ 8 int p,q,v; 9 }s[M]; 10 int dp[N]; 11 bool cmp(S a,S b){ 12 return (a.q-a.p)<(b.q-b.p); 13 } 14 int main(){ 15 int n,m; 16 while(cin>>n>>m){ 17 for(int i=1;i<=n;i++) 18 cin>>s[i].p>>s[i].q>>s[i].v; 19 sort(s+1,s+1+n,cmp); 20 memset(dp,0,sizeof(dp)); 21 for(int i=1;i<=n;i++){ 22 for(int j=m;j>=s[i].p;j--){ 23 if(j>=s[i].q) 24 dp[j]=max(dp[j],dp[j-s[i].p]+s[i].v); 25 } 26 } 27 int ans=-1; 28 for(int i=0;i<=m;i++) 29 ans=max(ans,dp[i]); 30 cout<<ans<<endl; 31 } 32 return 0; 33 }