洛谷 动态规划的背包问题(普及连续场)

                                             动态规划的背包问题

P1049 装箱问题 题目链接:https://www.luogu.org/problemnew/show/P1049

    题解:01背包裸题

    AC代码:

#include <bits/stdc++.h>
using namespace std;
#define _for(i,a,b) for(int i=a;i<=b;i++)
const int maxn = 20007;
int n,m,a[35],dp[maxn];
int main(int argc, char const *argv[])
{
	cin>>m>>n;
	_for(i,1,n)cin>>a[i];
	_for(i,1,n)
	{
		for(int j = m;j>=a[i];j--)
		{
			dp[j]=max(dp[j],dp[j-a[i]]+a[i]);
		}
	}
	cout<<m-dp[m]<<endl;
	return 0;
}

P1048 采药 题目链接:https://www.luogu.org/problemnew/show/P1048

题解:将时间看作背包容积即可,背包问题

   AC代码:

#include <bits/stdc++.h>
using namespace std;
#define _for(i,a,b) for(int i=a;i<=b;i++)
const int maxn = 107;
const int N = 1006;
int n,m,val[maxn],weight[maxn],dp[N];
int main(int argc, char const *argv[])
{
	cin>>m>>n;
	_for(i,1,n)cin>>weight[i]>>val[i];
	_for(i,1,n)
	{
		for(int j=m;j>=weight[i];j--)
		{
			dp[j]=max(dp[j],dp[j-weight[i]]+val[i]);
		}
	}
	cout<<dp[m]<<endl;
	return 0;
}

P1616 疯狂的采药 题目链接:https://www.luogu.org/problemnew/show/P1616

   题解:完全背包问题,将01背包的转换方程反过来写即可。

   AC代码

#include <bits/stdc++.h>
using namespace std;
#define _for(i,a,b) for(int i=a;i<=b;i++)
const int maxn = 10007;
const int N = 100006;
int n,m,val[maxn],weight[maxn],dp[N];
int main(int argc, char const *argv[])
{
	cin>>m>>n;
	_for(i,1,n)cin>>weight[i]>>val[i];
	_for(i,1,n)
	{
		_for(j,weight[i],m)
		{
			dp[j]=max(dp[j],dp[j-weight[i]]+val[i]);
		}
	}
	cout<<dp[m]<<endl;
	return 0;
}

P1064 金明的预算方案 题目链接:https://www.luogu.org/problemnew/show/P1064

   题解:重要度*价格就是价值,因为最多两个附件,所以在原本的转移方程上多出了三个选择,分别是选择第一     个附件,选择第二个附件,或者附件都选,那么加三个转移方程即可。
    AC代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 66;
const int N = 32006;
#define _for(i,a,b) for(int i=a;i<=b;i++)
int n,m,main_val[maxn],main_weight[maxn],dp[N],vis[maxn],val[maxn][3],weight[maxn][3];
int main(int argc, char const *argv[])
{
	cin>>m>>n;
	_for(i,1,n)
	{
		int x,y,z;
		cin>>main_weight[i]>>y>>z;
		if(z==0)main_val[i]=main_weight[i]*y;
		else if(weight[z][0]!=0)
		{
			weight[z][1]=main_weight[i];
			val[z][1]=main_weight[i]*y;
		}
		else
		{
			weight[z][0]=main_weight[i];
			val[z][0]=main_weight[i]*y;
		}
	}
	_for(i,1,n)
	{
		for(int j=m;j>=main_weight[i];j--)
		{
			dp[j]=max(dp[j],dp[j-main_weight[i]]+main_val[i]);
			if(j>=main_weight[i]+weight[i][0])
			{
				dp[j]=max(dp[j],dp[j-main_weight[i]-weight[i][0]]+val[i][0]+main_val[i]);
			}
			if(j>=main_weight[i]+weight[i][1])
			{
				dp[j]=max(dp[j],dp[j-main_weight[i]-weight[i][1]]+val[i][1]+main_val[i]);
			}
			if(j>=main_weight[i]+weight[i][0]+weight[i][1])
			{
				dp[j]=max(dp[j],dp[j-main_weight[i]-weight[i][0]-weight[i][1]]+val[i][0]+main_val[i]+val[i][1]);
			}
		}
	}
	cout<<dp[m]<<endl;
	return 0;
}

P1164 小A点菜 题目链接:https://www.luogu.org/problemnew/show/P1164

   题解:设dp[i][j]为吃到第i道菜时花费j元的状态,那么状态转移方程就是能不能吃和是否正好吃掉,

 (1)if(j==第i道菜的价格)f[i][j]=f[i-1][j]+1;

 (2)if(j>第i道菜的价格) f[i][j]=f[i-1][j]+f[i-1][j-第i道菜的价格];

 (3)if(j<第i道菜的价格) f[i][j]=f[i-1][j];

   AC代码:

/*
* @Author: 王文宇
* @Date:   2018-03-02 14:38:17
* @Last Modified by:   王文宇
* @Last Modified time: 2018-03-06 12:57:37
*/
#include <bits/stdc++.h>
using namespace std;
const int maxn = 107;
const int N = 10006;
#define _for(i,a,b) for(int i=a;i<=b;i++)
int n,m,dp[maxn][N],a[maxn];
int main(int argc, char const *argv[])
{
	cin>>n>>m;
	_for(i,1,n)cin>>a[i];
	_for(i,1,n)
	{
		_for(j,1,m)
		{
			if(a[i]==j)dp[i][j]=dp[i-1][j]+1;
			else if(a[i]>j)dp[i][j]=dp[i-1][j];
			else dp[i][j]=dp[i-1][j]+dp[i-1][j-a[i]];
		}
	}
	cout<<dp[n][m]<<endl;
	return 0;
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值