洛谷 1417

      这道题应该可以看出是背包问题,转移方程为f[i][j]=max(f[i-1][j],f[i-1][j-c[i]]+a[i]-j*b[i]),但是如果我们只是这样转移的话会出现问题,这道题与01背包的不同在于每个物品的价值与它放入的顺序有关,因为它的价值是a[i]-j*b[i],怎么办呢?我们考虑一下是否已经存在一种顺序使按照这种顺序装的话价值最大呢?类比与国王游戏那道题,我们考虑一下,假设当前1号在2号前面,此时1号与2号的价值和是a[1]+a[2]-c[1]*b[1]-(c[1]+c[2])*b[2],如果我们交换1号与2号的顺序,可以知道这样是对后面没有影响,那么我们换完以后的价值和是a[1]+a[2]-c[2]*b[2]-(c[1]+c[2])*b[1],如果这次交换能使价值变大,那么我们可以推出c2*b1<c1*b2,这样我们推广一下,如果相邻两个物品出现了这种情况,我们可以把它们交换,这是不是很像冒泡排序?那们我们按照这种方式进行排序最终序列就是确定的了,这样就变成了普通的01背包,但是注意物品的价值仍与剩余体积有关系,因此我们在用滚动数组优化时注意取最优解。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 100005
typedef long long LL;
LL f[maxn],ans;
int a[55],b[55],c[55],n,m;

int main()
{
	scanf("%d%d",&m,&n);
	for (int i=1;i<=n;i++) scanf("%d",a+i);
	for (int i=1;i<=n;i++) scanf("%d",b+i);
	for (int i=1;i<=n;i++) scanf("%d",c+i);
	for (int i=1;i<=n;i++) 
		for (int j=i+1;j<=n;j++) 
			if ((LL)c[i]*(LL)b[j]>(LL)c[j]*(LL)b[i]) 
			{
				swap(a[i],a[j]);
				swap(b[i],b[j]);
				swap(c[i],c[j]);	
			}
	for (int i=1;i<=n;i++) 
		for (int j=m;j>=c[i];j--)
			f[j]=max(f[j],f[j-c[i]]+(LL)a[i]-(LL)j*(LL)b[i]);
	//printf("%lld\n",f[m]);
	for (int i=1;i<=m;i++) ans=max(ans,f[i]);
	printf("%lld\n",ans);
	return 0;	
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值