蓝桥杯试题 算法提高 01背包

蓝桥杯试题 算法提高 01背包

题目描述:

资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
  给定N个物品,每个物品有一个重量W和一个价值V.你有一个能装M重量的背包.问怎么装使得所装价值最大.每个物品只有一个.
输入格式
  输入的第一行包含两个整数n, m,分别表示物品的个数和背包能装重量。
  以后N行每行两个数Wi和Vi,表示物品的重量和价值
输出格式
  输出1行,包含一个整数,表示最大价值。
样例输入
3 5
2 3
3 5
4 7
样例输出
8
数据规模和约定
  1<=N<=200,M<=5000.
  
一开始我使用的是dfs解法,即,一个物品有两个状态,可以装,可以不装,遍历所有情况,输出最优解,毫无疑问,思路没有毛病,但是超时了,毕竟时间复杂度为O(2的n次方),所以超时也是正常的。

dfs解法的代码【超时】如下:

#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
struct Node
{
	int w;
	int v;
}a[200];
int n,m,answer=0;
void f(int step,int ans,int m)
{
	if(step==n||m<=0)
	{
		if(answer<ans)
			answer=ans;
		return;		
	}
	f(step+1,ans,m);//不选择该物品 
	if(m>=a[step].w)
		f(step+1,ans+a[step].v,m-a[step].w);//选择该物品 
}
int main()
{
	int i;
	cin>>n>>m;
	for(i=0;i<n;i++)
		cin>>a[i].w>>a[i].v; 
	f(0,0,m);
	cout<<answer<<endl;
	return 0;
}

那么应该怎么做呢,dfs解法之所以超时,就是因为重叠子问题,我们可以使用数组存储前面计算的解法,后面就可以直接用啦,比如我们的目的是求得在n个物品中进行选择,背包总容量为m的情况下的最优解就是求得在前n-1个物品中进行选择的情况下的最优解,然后加上选择第n个物品,或者不选择第n个物品的最大值。
如果不了解动态规划,可以看下B站的这个视频,贼详细,小哥哥讲的。

动态规划01背包详解

如果我们用数组dp[i][j]表示在前i个物品中进行选择,背包容量为j的最优解。那么dp[i][j]为:

dp[i][j]=max(dp[i-1][j-things[i].w]+things[i].v,dp[i-1][j]); 

但是并不是每个物品都可以装进去,所以我们需要考虑,当第i个物品装不下,就只能不装啦,那么dp[i][j]为:

dp[i][j]=dp[i-1][j];

AC代码:

#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
struct node
{
	int w;//每个物品的重量 
	int v;//每个物品的价值 
}things[210];
int dp[210][5010];
int main()//动态规划解法 
{
	int n,m,i,j;//n代表一共n个物品,m代表背包的总容量
	cin>>n>>m;
	
	for(i=1;i<=n;i++)
		cin>>things[i].w>>things[i].v;
	
	for(i=1;i<=n;i++)
		for(j=1;j<=m;j++)//dp[i][j]代表总共有前i个物品,背包容量为j的情况下的最优解(此时价值最大) 
		{
			if(j<things[i].w)//背包不能装下第i个物品
				dp[i][j]=dp[i-1][j];
			else
				dp[i][j]=max(dp[i-1][j-things[i].w]+things[i].v,dp[i-1][j]); 
		}
	cout<<dp[n][m]<<endl;
} 

你可能感兴趣的:(蓝桥,动态规划)