HDU 2602 Bone Collector【01揹包】

HDU 2602 Bone Collector 

大致意思:n個骨頭,不同骨頭價值和重量不同,知道揹包的容量s,求最大價值。

--------------------------------------------------------------------------------------------------------------------------------------------------

動態規劃先找出子問題,我們可以這樣考慮:在物品比較少,揹包容量比較小時怎麼解決?用一個數組dp[i][j]表示,在只有i個物品,容量爲j的情況下揹包問題的最優解,那麼當物品種類變大爲i+1時,最優解是什麼?第i+1個物品可以選擇放進揹包或者不放進揹包,假設放進揹包(前提是放得下),那麼dp[i+1][j]=dp[i][j-weight[i+1]+value[i+1];

如果不放進揹包,那麼dp[i+1][j]=dp[i][j]。放不下就是dp[i+1][j]=dp[i][j];

這就得出了狀態轉移方程:

dp[i+1][j]=max(dp[i][j],dp[i][j-weight[i+1]+value[i+1])

/**01揹包**/
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn=1010;
int w[maxn];//重量 
int v[maxn];//價值 
int dp[maxn][maxn];
int n,s;
 
void slove()
{
    for(int i = 1; i <= n; i++)
    {
        for(int j = 0; j <= s; j++)
        {
            if(j < w[i])///揹包容量比第i個物品的重量小
                dp[i][j]  = dp[i-1][j];
            else
                dp[i][j] =  max(dp[i-1][j], dp[i-1][j - w[i]] + v[i]);
            cout << dp[i][j] << ' ';
        }
        cout << endl;
    }
}
 
int main()
{
    
    int T;
    cin>>T;
    while(T--)
    {
        memset(dp,0,sizeof(dp));
        cin>>n>>s;
        for(int i=1; i<=n; i++)
            cin>>v[i];//價值 
        for(int i=1; i<=n; i++)
            cin>>w[i];//重量
        slove();
        cout << dp[n][s] << endl;
    }
    return 0;
}

 -------------------------------------------------------------------------------------------------------------------------------------------------------------------

上面計算 dp[i][j]可以看出,在計算  dp[i][j]時只使用了 dp[i-1][0……j],沒有使用其他子問題,因此在存儲子問題的解時,只存儲 dp[i-1]子問題的解即可。這樣可以用兩個一維數組解決,一個存儲子問題,一個存儲正在解決的子問題。再進一步思考,計算dp[i][j]時只使用了 dp[i-1][0……j],沒有使用dp[i-1][j+1]這樣的話,我們先計算j的循環時,讓j=M……1,只使用一個一維數組即可。這就得出了狀態轉移方程:

dp[j]=max(dp[j],dp[j-weight[i]+value[i]) ;

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int dp[1010],weight[1010],value[1010];//全局變量,自動清0; 
int main()
{
	int t,n,m,i,j;
	cin>>t;
	while(t--) 
	{
		memset(dp,0,sizeof(dp));//記得清0; 
		cin>>n>>m;
		for(i=1;i<=n;i++)
			cin>>value[i];
		for(i=1;i<=n;i++)
			cin>>weight[i];
		for(i=1;i<=n;i++)
		{
			for(j=m;j>=weight[i];j--)
			{
				dp[j]=max(dp[j],dp[j-weight[i]]+value[i]);
			}
		}
		cout<<dp[m]<<endl;
	}
	return 0;
} 

 

發佈了95 篇原創文章 · 獲贊 16 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章