完全背包问题--最小乘车费用(busses)

关于一维背包和完全背包问题都会在这进行讲解

 首先一维背包,如何从二维背包中转换,我们可以从原先的代码提取一点信息

#include<bits/stdc++.h>
using namespace std;
    int a[1010];
    int w[1010];
    int v,m;
    int dp[1500][1500];
int main()
{
    cin>>v>>m;
    for(int i=1;i<=m;i++)
    {
        cin>>a[i]>>w[i];
    }
    for(int i=1;i<=m;i++)
    {   
        for(int j=v;j>=1;j--)
        {
        	if(j<a[i])
        	dp[i][j]=dp[i-1][j];
        	else
            dp[i][j]=max(dp[i-1][j],dp[i-1][j-a[i]]+w[i]);
        }
    }
//    for(int i=1;i<=m;i++)
//	{
//		for(int j=1;j<=v;j++)
//		{
//			cout<<dp[i][j]<<" ";
//		}
//		cout<<endl;
//	} 
    cout<<dp[m][v]<<endl;
    return 0;
}

 

 我们可以看到他是每次都从i-1中提取出来的,那么现在不用i-1直接用后边那个j来表示的结果,如下图所示其中次数代表着外层循环,第i次的f数组的所有元素值。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int v[10010];
int w[10010];
int a[10010];
int main()
{
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		cin>>v[i]>>w[i];
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=m;j>=v[i];j--)
		{
			a[j]=max(a[j],a[j-v[i]]+w[i]);
		}
	}
	cout<<a[m];
	return 0;
}

 其中动态转移方程是倒着写推的,他的目的是不重复利用同一个物品,那完全背包是什么,就是同一个物品可以利用多次,所以我们的动态转移方程就可以正着写,直接借鉴01背包问题,附赠一个推导图,多推导几次就差不多能会。(上边的为01背包,下边的为完全背包,放在一起方便对比)

 

 

#include<bits/stdc++.h>
using namespace std;
int a[11];
int f[100010];
int main()
{
	int n=10;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
	}
	int m;
	cin>>m;
	f[0]=0;
	for(int i=1;i<=m;i++)
	{
		f[i]=i*a[1];
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			if(j-i>=0)
			f[j]=min(f[j],f[j-i]+a[i]);
		}
	}
	cout<<f[m]<<endl;
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sky逆流而上

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值