杭電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;
}
講起來倒是容易理解,寫到部落格才感覺好多東西是寫不出來的,加油吧