Bone Collector
Bone Collector
Time Limit : 2000/1000ms (Java/Other) Memory Limit : 32768/32768K (Java/Other)
Total Submission(s) : 11 Accepted Submission(s) : 10
Problem Description
Many years ago , in Teddy’s hometown there was a man who was called “Bone Collector”. This man like to collect varies of bones , such as dog’s , cow’s , also he went to the grave … The bone collector had a big bag with a volume of V ,and along his trip of collecting there are a lot of bones , obviously , different bone has different value and different volume, now given the each bone’s value along his trip , can you calculate out the maximum of the total value the bone collector can get ? [center][img]../../../data/images/C154-1003-1.jpg[/img] [/center]
Input
The first line contain a integer T , the number of cases. Followed by T cases , each case three lines , the first line contain two integer N , V, (N <= 1000 , V <= 1000 )representing the number of bones and the volume of his bag. And the second line contain N integers representing the value of each bone. The third line contain N integers representing the volume of each bone.
Output
One integer per line representing the maximum of the total value (this number will be less than 2[sup]31[/sup]).
Sample Input
1
5 10
1 2 3 4 5
5 4 3 2 1
Sample Output
14
Author
Teddy
Source
HDU 1st “Vegetable-Birds Cup” Programming Open Contest
题目大意:
和01背包差不多,第一行输入T组测试样例,每一组测试样例有三行,第一行时输入两个数据N和V,N表示有多少个的骨头。V表示背包的最大容量。当然,每一个骨头都有自己的价值和重量。下一行就是让你输入每一个骨头对应的价值,接下去一行就是让你输入对应骨头的重量。然后,询问你有V的容量大小的背包,最多可以装多少价值的骨头。(每一个骨头都是唯一的,仅能装一次,背包可以不用装满)。
状态:
用SIGN[j]来保存每一次向背包大小为j的背包装入骨头,所能装入的最大价值。
PACK[i]用来保存出入骨头的价值和重量。
状态转移方程:
SIGN[j]=MAX{SIGN[j-PACK[i].Volume]+PACK[i].Value,SIGN[j]};/*装入第i个骨头的时候,判断是否需要更新相关背包容量的最大价值*/
空间复杂度:O(V), 时间复杂度O(N*V);
1 #include<stdio.h> 2 #include<string.h> 3 typedef struct 4 { 5 int Value ; 6 int Volume ; 7 }XY; 8 XY PACK[1010];/*保存物品的价值和重量*/ 9 int SIGN[1010];/*依次保存每一个背包大小所能存放的最大价值*/ 10 11 int main() 12 { 13 int T,N,V,i,j; 14 scanf("%d",&T); 15 while(T--) 16 { 17 scanf("%d%d",&N,&V); 18 memset(SIGN,0,sizeof(SIGN));/*因为背包可以不用装满,所以初始化为0*/ 19 for(i=0;i<N;i++) 20 scanf("%d",&PACK[i].Value); /*输入每一个骨头的价值*/ 21 for(i=0;i<N;i++) 22 scanf("%d",&PACK[i].Volume); /*输入每一个骨头的重量*/ 23 for(i=0;i<N;i++) /*当装入第(i+1)个骨头的时候,更新SIGN[]上的最大价值*/ 24 for(j=V;j>=PACK[i].Volume;j--) /*因为每一个骨头都是唯一存在的,仅能装一次,所以需要从后面开始*/ 25 { /*才不会出现有重复累加同一个骨头的部分,从后开始可以保证每一次*/ 26 if(SIGN[j]<(SIGN[j-PACK[i].Volume]+PACK[i].Value)) /*装入的骨头都是与之前装入的骨头没有关系*/ 27 SIGN[j]=SIGN[j-PACK[i].Volume]+PACK[i].Value; /*否则会出现,唯一能装入一次的骨头多次被装入*/ 28 if(i==N-1)break; /*在添加最后一个数据后,比较更新,即可*/ 29 } 30 printf("%d\n",SIGN[V]); /*既为输出背包容量为V,所能存的骨头的最大价值,也为题目所求的*/ 31 } 32 return 0; 33 }
用DP[i][j]记录的做法:
#include <iostream> #include <string.h> #include <stdio.h> #define Max(a,b)(a>b?a:b) using namespace std; int DP[1010][1010]={0};/*DP[i][j]表示放第i个物品,j表示当前背包的容量,放第i个物品,容量为j的最大价值*/ /*DP[i][j]取决于放第i-1个物品容量为j-W[i]的价值+V[i]的价值和放第i-1个物品容量为j的时候的最大值*/ /*DP[i][j]=max(DP[i-1][i-W[i]]+V[i],DP[i-1][j]);当j>=W[i]时*/ /*DP[i][j]=DP[i-1][j];当j<W[i]时*/ int main() { int T,n,m,i,j; int W[1010]; int V[1010]; int Num[1010]; scanf("%d",&T); while(T--) { scanf("%d %d",&n,&m); for(j=1;j<=n;j++)scanf("%d",&V[j]);/*第i个物品的权值*/ for(i=1;i<=n;i++)scanf("%d",&W[i]);/*第i个物品的重量*/ // memset(DP,0,sizeof(DP));/*初始化DP*/ for(i=1;i<=n;i++)/*n个物品*/ { for(j=0;j<=m;j++)/*遍历所有能够装下的背包容量*/ { if(j>=W[i]) DP[i][j]=Max(DP[i-1][j-W[i]]+V[i],DP[i-1][j]); else DP[i][j]=DP[i-1][j]; //printf("%d ",DP[i][j]); } // putchar(10); } printf("%d\n",DP[n][m]);/*放第n个物品,背包容量为m的价值的最大值*/ } return 0; }
转载请备注:
**************************************
* 作者: Wurq
* 博客: https://www.cnblogs.com/Wurq/
* Gitee: https://gitee.com/wurq
**************************************
**************************************
* 作者: Wurq
* 博客: https://www.cnblogs.com/Wurq/
* Gitee: https://gitee.com/wurq
**************************************

浙公网安备 33010602011771号