对于每个物品,如果购买,价值为A[i]*x+B[i]的背包问题。
先写了一发是WA的= =。代码如下:
1 #include <stdio.h> 2 #include <algorithm> 3 #include <string.h> 4 #include <set> 5 using namespace std; 6 typedef pair<int,int> pii; 7 8 pii dp[2005]; 9 int w[1005],A[1005],B[1005]; 10 11 int main() 12 { 13 int T;scanf("%d",&T); 14 while(T--) 15 { 16 int m,n;scanf("%d%d",&m,&n); 17 for(int i=1;i<=n;i++) scanf("%d%d%d",w+i,A+i,B+i); 18 for(int i=0;i<=m;i++) dp[i] = pii(0,0); 19 for(int i=1;i<=n;i++) 20 { 21 for(int j=0;j<=m;j++) dp[j] = pii(dp[j].first, 0); 22 for(int j=w[i];j<=m;j++) 23 { 24 if(dp[j-w[i]].first + A[i] + (dp[j-w[i]].second == 0 ? B[i] : 0) > dp[j].first) 25 { 26 dp[j].first = dp[j-w[i]].first + A[i] + (dp[j-w[i]].second == 0 ? B[i] : 0); 27 dp[j].second = 1; 28 } 29 } 30 } 31 printf("%d\n",dp[m].first); 32 } 33 return 0; 34 }
正解是,先跑一遍价值为A[i]+B[i]的01背包,再跑一遍价值为A[i]完全背包。所以上面的代码错了大概是因为,这两个背包的第二个for的方向是不同的,没办法一起跑吧(除非用另外一组变量记录下到前一个为止的dp值,然后就可以同时跑了)。。对背包问题的理解还是不够深啊。。
————————————————————————————————————————————————————————
想了一下,感觉上面说的括号里的再用一个数组记录的方法貌似不太对。。虽然那份代码AC了- -。。反正跑两遍的方法肯定是对的。。我说的是这个博客里面的第二个方法:http://www.cnblogs.com/wmxl/p/4749780.html。也有可能是我对完全背包的理解不够深刻。。先放着再说好了。。
————————————————————————————————————————————————————————
AC代码如下:
1 #include <stdio.h> 2 #include <algorithm> 3 #include <string.h> 4 #include <set> 5 using namespace std; 6 typedef pair<int,int> pii; 7 8 int dp[2005]; 9 int w[1005],A[1005],B[1005]; 10 11 int main() 12 { 13 int T;scanf("%d",&T); 14 while(T--) 15 { 16 int m,n;scanf("%d%d",&m,&n); 17 for(int i=1;i<=n;i++) scanf("%d%d%d",w+i,A+i,B+i); 18 memset(dp,0,sizeof(dp)); 19 for(int i=1;i<=n;i++) 20 { 21 for(int j=m;j>=w[i];j--) dp[j] = max(dp[j], dp[j-w[i]] + A[i] + B[i]); 22 for(int j=w[i];j<=m;j++) dp[j] = max(dp[j], dp[j-w[i]] + A[i]); 23 } 24 printf("%d\n",dp[m]); 25 } 26 return 0; 27 }