1. 程式人生 > >杭電ACM-2602 Bone Collector

杭電ACM-2602 Bone Collector

                                           Bone Collector

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 87013    Accepted Submission(s): 35933


 

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 ?

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 231).

Sample Input

1

5 10

1 2 3 4 5

5 4 3 2 1

Sample Output

14

藉著這個題學習一下01揹包吧,學貪心不久,算這種揹包問題一直用算價值比較,然後加到空間佔滿來著,結果這個題交了N遍都沒過,無奈只能找別的方法了,看了一下這位大佬才知道可以這麼用,表格可以說讓人看起來很清楚了,拷到這大家看一下吧。

https://blog.csdn.net/shellhard/article/details/62083266

簡單說一下吧,核心程式碼就是下面這一段

        for(int i=1;i<=n;i++)
		{
		  for(int j=0;j<=m;j++)  //從0開始意味著重量為0也可以計算
			{
				if(j>=w[i])
				{

					s[i][j]=max(s[i-1][j],s[i-1][j-w[i]]+v[i]);   

                   //  此時的值是[i-1][j-w[i]]+v[i]   和   [i-1][j]比較
				}
				else
					s[i][j]=s[i-1][j];
			}
		}

       左邊代表骨骼的數量,從0到5,總體積為10,從1排到10,

我們定義一個二維陣列m[ i ][ j ]  i表示第i個骨骼,j表示揹包容量為j;

       用0-1揹包的問題來求解,就是要得到每一步的最優解,此時第i個物品面臨選擇,首先我們要看容量是否大於它的重量,

       即 j > w[ i ]

如果大於,我們可以選擇拿或不拿

       1:拿,那麼就必須要佔用當前揹包的空間。即用當前揹包總容量 j - w[ i ],再佔用1個物品空間,所以i-1,此時的總價值就是m [ i-1 ] [ j-w[ i ] ] 的解 + 當前的價值v[ i ] ,得到的就是放入當前物品得到的最優解。

       2:不拿,那麼就還是上一步的解,m[ i-1 ][ j ]

下面是AC程式碼:

//#include<bits/stdc++.h>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
using namespace std;
int w[1003];        //體積
int v[1003];        //價值
int s[1003][1003];
int main()
{
	int t,n,m;

	cin>>t;
	while(t--)
	{
		memset(s,0,sizeof(s));
		cin>>n>>m;
		for(int i=1;i<=n;i++)
		{
			cin>>v[i];      //每個骨骼的價值
		}
		for(int i=1;i<=n;i++)
		{
			cin>>w[i];       //每個骨骼的體積
		}
		
		//0-1揹包
		for(int i=1;i<=n;i++)
		{
			for(int j=0;j<=m;j++)  //從0開始意味著重量為0也可以計算
			{
				if(j>=w[i])
				{
					s[i][j]=max(s[i-1][j],s[i-1][j-w[i]]+v[i]);   //  此時的值是[i-1][j-w[i]]+v[i]   和   [i-1][j]比較
				}
				else
					s[i][j]=s[i-1][j];
			}
		}
		cout<<s[n][m]<<endl;
	}
	return 0;
}

講起來倒是容易理解,寫到部落格才感覺好多東西是寫不出來的,加油吧