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
因爲所求問題是n件物品,揹包限重爲m,隨着問題規模的增減,n 和m都在變化,因此很自然地想到把件數和揹包限重都作爲自變量。定義函數f(i,j)爲在1~I 件物品中選若干件裝入限重爲j的揹包中的最大價值和。
當第I件物品要裝入揹包時,f(I,j) := I-1件物品,限重爲j-w[I]的最優解+ v[I], 即:f(I,j) := f(I-1, j-w[I]) + v[I]
當然,第I件物品要裝入是有條件限制的,是什麼?
第I件物品重量小於等於揹包限重,即 w[I] <= j
當第I件物品不裝入揹包時,f(I,j) := I-1件物品,限重爲m的最優解,即:
f(I,j) := f(I-1, j)
現在已經求得裝入或者不裝入第I件物品的限重爲J的揹包的最大價值,那麼接下來應該做什麼?
比較這兩種情況下誰的價值更大,更大者爲當前問題的最優解。
if f(I,j)’ > f(I,j)’’ then
f(I,j) := f(I,j)’
else
f(I,j) := f(I,j)’’;
上述遞歸式的邊界條件是什麼?
我們知道f(I,j)的I和J都有一個取值範圍。1<=I<=n, 0 <=J<=m. 邊界條件就是當問題規模縮小到自變量下界時的函數的取值情況。
當揹包限重爲0時,無法放任何物品,此時所有的f(I,0) := 0 (1<=I<=n). 這就是邊界條件。
解1:二維數組
#include<cstdio>
#include<algorithm>
using namespace std;
int dp[1005][1005] = {0};
/*dp[i][j]爲在1~I 件物品中選若干件裝入限重爲j的揹包中的最大價值和。*/
int main()
{
int t;
scanf ("%d",&t);
while (t--)
{
int n,v;
scanf ("%d%d",&n,&v);
int value[1005],volume[1005];
for (int i=1; i<=n; i++)
{
scanf ("%d",&value[i]);
}
for (int i=1; i<=n; i++)
{
scanf ("%d",&volume[i]);
}
for (int i=1; i<=n; i++)
{
for (int j=0; j<=v; j++)
{
if (j < volume[i])
{
dp[i][j] = dp[i-1][j];
}
else
{
dp[i][j] = max(dp[i-1][j],dp[i-1][j-volume[i]]+value[i]);
}
}
}
printf ("%d\n",dp[n][v]);
}
return 0;
}
二維數組最重要的一點是要注意數組開闢的空間,由於這道題的要求,1005*1005將會佔大片空間,所以要定義在主函數外。
解2 :一維數組
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
int t;
scanf ("%d",&t);
while (t--)
{
int n,v;
int value[1005],volume[1005];
int i,j;
scanf ("%d%d",&n,&v);
for (i=0; i<n; i++)
{
scanf ("%d",&value[i]);
}
for (i=0; i<n; i++)
{
scanf ("%d",&volume[i]);
}
int dp[1005] = {0};
for (i=0; i<n; i++)
{
for (j=v; j>=volume[i]; j--)
{
dp[j] = max(dp[j],dp[j-volume[i]]+value[i]);
}
}
printf ("%d\n",dp[v]);
}
return 0;
}