0-1背包

例六、 Charm Bracelet 0-1背包问题(POJ3624)
有N件物品和一个容积为M的背包。第i件物品的体积 w[i],价值是d[i]。求解将哪些物品装入背包可使价值总 和最大。每种物品只有一件,可以选择放或者不放 (N<=3500,M <= 13000)。
21

0-1背包问题(POJ3624)
用 F[i][j] 表示取前i种物品,使它们总体积不超过j的最优 取法取得的价值总和。要求F[N][M]
边界:if (w[1] <= j)
F[1][j] = d[1];
else
F[1][j] = 0;
22

0-1背包问题(POJ3624)
用 F[i][j] 表示取前i种物品,使它们总体积不超过j的最优 取法取得的价值总和
递推: F[i][j] = max(F[i-1][j],F[i-1][j-w[i]]+d[i])
取或不取第 i种物品,两者选优 (j-w[i] >= 0才有第二项)
23

0-1背包问题(POJ3624)
F[i][j] = max(F[i-1][j],F[i-1][j-w[i]]+d[i])
本题如用记忆型递归,需要一个很大的二维数组,会 超内存。注意到这个二维数组的下一行的值,只用到了 上一行的正上方及左边的值,因此可用滚动数组的思想 ,只要一行即可。即可以用一维数组,用“人人为我” 递推型动归实现。

递归:

#include <iostream>
using namespace std;
int W[10];
int D[10];
int F(int i,int j){
    if(i==1&&W[1]<=j) return D[1];
    else if(i==1)return 0;
    if(j-W[i]>=0)
    return max(F(i-1,j),F(i-1,j-W[i])
    +D[i]);else{
        return F(i-1,j);
    }
}
int main(){
        for(int i=1;i<=3;i++)
        {
            cin>>W[i];
        }
        for(int j=1;j<=3;j++)
        cin>>D[j];
    cout<<F(3,40);
    

}

递推:节省空间

#include <iostream>
using namespace std;
int w[10];
int n;
int j;
int d[10];
int F[100];//滚动数组
int main(){
	cin>>n;
	cin>>j;
	for(int i=1;i<=n;i++){
		cin>>w[i];
	}
	for(int i=1;i<=n;i++){
		cin>>d[i];
		}
	for(int k=0;k<=j;k++)
	{
		if(w[1]<=k) F[k]=d[1];
		else F[k]=0;
	}
	int temp=0;
	for(int i=2;i<=n;i++)//状态只用到正上方和左侧,所以从最右侧开始递推
	{
	for(int k=j;k>=0;k--)
	{
		if(k>=w[i])
		{			
			temp=max(F[k],F[k-w[i]]+d[i]);
			F[k]=temp;
	
	}
	
	}
	cout<<F[j];
}

 

posted @ 2021-12-23 10:44  坤k  阅读(49)  评论(0编辑  收藏  举报