背包问题(1)-01背包

背包问题(Knapsack problem)是一种组合优化的NP完全问题。问题可以描述为:给定一组物品,每种物品都有自己的重量和价格,在限定的总重量内,我们如何选择,才能使得物品的总价格最高。问题的名称来源于如何选择最合适的物品放置于给定背包中。相似问题经常出现在商业、组合数学,计算复杂性理论、密码学和应用数学等领域中。也可以将背包问题描述为决定性问题,即在总重量不超过W的前提下,总价值是否能达到V?它是在1978年由Merkle和Hellman提出的。

01背包
问题描述:
给定n种物品和一背包。物品i的重量是wi,其价值为vi,背包的容量为C。问应如何选择装入背包的物品,使得装入背包中物品的总价值最大?

算法分析:

二维做法
用一个数组f[i][j]表示,在只有i个物品,容量为j的情况下背包问题的最优解,那么当物品种类变大为i+1时,最优解是什么?第i+1个物品可以选择放进背包或者不放进背包(这也就是0和1),假设放进背包(前提是放得下),那么f[i+1][j]=f[i][j-w[i+1]+v[i+1];如果不放进背包,那么f[i+1][j]=f[i][j]。
这就得出了状态转移方程:

f[i+1][j]=max(f[i][j],f[i][j-w[i+1]+v[i+1])
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
using namespace std;
const int MAX=2147483647;
const int N=2e2+10;
int f[40][N],w[40],v[40],n,C; 
int main()
{
	//fre();
	scanf("%d%d",&C,&n);
	for(int i=1;i<=n;i++) scanf("%d%d",&w[i],&v[i]);
	for(int i=1;i<=n;i++) 
		for(int j=C;j>0;j--)
		{
			if(w[i]<=j)	f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+v[i]);	
			else f[i][j]=f[i-1][j];
		}
	printf("%d",f[n][C]);			
	return 0;
}

一维做法:

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
using namespace std;
const int MAX=2147483647;
const int N=2e2+10;
int f[N],w[40],v[40],n,C; 
int main()
{
	//fre();
	scanf("%d%d",&C,&n);
	for(int i=1;i<=n;i++) scanf("%d%d",&w[i],&v[i]);
	for(int i=1;i<=n;i++) 
		for(int j=C;j>=w[i];j--)
			if(w[i]<=j)	f[j]=max(f[j],f[j-w[i]]+v[i]);	
	printf("%d",f[C]);			
	return 0;
}


其他背包问题:
背包问题(2)-完全背包

原创文章 157 获赞 148 访问量 8320

猜你喜欢

转载自blog.csdn.net/bigwinner888/article/details/105668266