问题描述:
以后N行每行两个数Wi和Vi,表示物品的重量和价值
2 3
3 5
4 7
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 5 int max(int a,int b) 6 { 7 return a>b?a:b; 8 } 9 10 int main() 11 { 12 int n,m; 13 scanf("%d%d",&n,&m); 14 15 int *w,*v; 16 w=(int *)malloc(sizeof(int)*n); 17 v=(int *)malloc(sizeof(int)*n); 18 19 int **arr; //动态分配二维数组 20 arr=(int **)malloc(sizeof(int *)*(n+1)); 21 int i; 22 for(i=0;i<=n;i++) 23 arr[i]=(int *)malloc(sizeof(int)*(m+1)); 24 25 int j; 26 for(i=0;i<=n-1;i++) 27 scanf("%d%d",&w[i],&v[i]); 28 for(i=0;i<=n;i++) 29 for(j=0;j<=m;j++) 30 { 31 if(i==0 || j==0) //0容量或者0物品置0 32 arr[i][j]=0; 33 else if(w[i-1]<=j) 34 arr[i][j]=max(arr[i-1][j],arr[i-1][j-w[i-1]]+v[i-1]); 35 else 36 arr[i][j]=arr[i-1][j]; 37 } 38 printf("%d",arr[n][m]); 39 free(arr); 40 free(w); 41 free(v); 42 return 0; 43 }
思路提升:
从上面的表格可以看到,我们用了一个二维数组存储了每一行的数据,但是实际情况是第1行数据只是第2行用,用完以后就没用了,
第 i 行的数据只是第 i+1 行使用,用完了就放在数组里面占用大量空间了;所以我们完全可以用一个 “滚动数组” 来实现这种操作,
所谓的滚动数组其实很简单,就是数组里面我们先存放第 1 行的数据,然后我们根据第 1 行的数据求出第 2 行的数据存放在数组;
就是第 i 行的数据先存放,我求出第 i+1 行的数据以后数组我来占用,这样不断变化的数组就是滚动数组,很简单吧。
代码实现:
1 #include<stdio.h> 2 #include<stdlib.h> 3 4 int max(int a,int b) 5 { 6 return a>b?a:b; 7 } 8 9 int main() 10 { 11 int n,m; 12 scanf("%d%d",&n,&m); 13 14 int *wi,*vi; 15 wi=(int *)malloc(sizeof(int)*(n+1)); 16 vi=(int *)malloc(sizeof(int)*(n+1)); 17 18 int i; 19 for(i=1;i<=n;i++) 20 scanf("%d%d",&wi[i],&vi[i]); 21 22 int *dp; 23 dp=(int *)malloc(sizeof(int)*(m+1)); //滚动数组 24 for(i=0;i<=m;i++) 25 dp[i]=0; 26 27 int j; 28 for(i=0;i<=n;i++) 29 for(j=m;j>=wi[i];j--) //容量从大到小 30 { 31 if(i==0) 32 { 33 dp[j]=0; 34 continue; 35 } 36 37 dp[j]=max(dp[j],dp[j-wi[i]]+vi[i]); 38 } 39 40 printf("%d",dp[m]); 41 return 0; 42 }
代码中状态方程变为:dp[j]=max(dp[j],dp[j-wi[i]]+vi[i]);
请大家注意,dp[j]代表的是现在要求的第 i 个物品考虑放不放在容量为 j 的物品下的最优解,而括号里面的dp[j]代表的
是放 i-1 个物品中的物品时的最优解,相当于上面的F[ i-1 ][ j ],也就是说这个是前一个状态的量,而dp[j-wi[i]]+vi[i]
就是上面的F[ i-1 ][ j - wi[i] ] + vi[ i ]了。但是容量 j 的值要从大到小了,因为我们求大容量背包的价值时要用到
小容量背包的价值,所以如果从小容量开始求,等到求放下一个物品时,从小容量开始求,那么当我们求这个物品的大容量时放与不放时
上一个物品的小容量值由于被这个物品的小容量值覆盖,所以要从大容量开始求。
2018-04-06