题目链接:http://poj.org/problem?id=3624
题意:一共给出n种手镯,每个手镯有着各自的重量以及魅力值,在m重量下能得到的最大魅力值是多少。
分析:标准的01背包。状态转移如此:
dp[i][j]表示前i个手镯在重量为j的背包容量下能达到的最大魅力值。w[i]是第i个手镯的重量,d[i]是第i个手镯的魅力值。
如果某个超过背包重量,则一定不放入背包。问题则为剩余i-1个手镯装入重量的容量为j的背包得到的最大魅力值。
否则该手镯放入背包。问题则为剩余i-1个手镯装入重量的容量为j-w[i]的背包能到的的最大价值加上手镯i的价值d[i]。
if (w[i]>j) dp[i][j] = dp[i-1][j]
else dp[i][j] = max(dp[i-1][j-w[i]]+d[i],dp[i-1][j])
第一次用二维写的,,,好吧,貌似只能用一维这题
手工模拟一下发现dp[i,j]只跟之前的某几个值有关,再之前计算的结果就都没用了...
所以我们就可以用一个数组来重复使用了,不过要倒序,保证无后效性...
Sample Input 4 6 1 4 2 6 3 12 2 7 Sample Output 23
AC代码:
1 #include<stdio.h> 2 #include<math.h> 3 #include<string.h> 4 #include<ctype.h> 5 #include<stdlib.h> 6 #include <iostream> 7 #include<algorithm> 8 #include<queue> 9 10 using namespace std; 11 12 #define N 13000 13 ///12880和3420你选哪个? 14 ///就不告诉你我之前写的是小的,不然也不会把二维的写出来啊,唉 15 int w[N],d[N],dp[N]; 16 17 int main() 18 { 19 int n,k,i,j; 20 21 while(scanf("%d%d", &n,&k) != EOF) 22 { 23 memset(dp,0,sizeof(dp));///清零清零 24 for(i=0;i<n;i++) 25 scanf("%d %d", &w[i], &d[i]); 26 27 for(i=0;i<n;i++) 28 for(j=k;j>=w[i];j--) 29 dp[j]=max(dp[j], dp[j-w[i]]+d[i]); 30 31 printf("%d ", dp[k]); 32 } 33 return 0; 34 }