【动态规划】春季特惠

http://oj.hzjingma.com/contest/problem?id=90&pid=2&_pjax=%23p0
在这里插入图片描述
比赛思路:
比赛的时候就看出来了这是一道01背包的模板题,但是应该要转换一下思路,可惜俺太笨了转换半天都没想出来。这个负数好难搞啊,而且背包的空间会变化的,这咋搞嘛;

题解思路:
考虑一下,心理满足的条件是
——总优惠大于超过预算的总金额。

而每一个物品都会有它的优惠值----- a[ i ] - b[ i ]
如果这物品的优惠值>=他的现价这说明其实这件物品是没有花费的。
而如果这件物品的优惠值<他的现价,也就是这件要有花费了,花费就是 现价-优惠值;这里的花费其实就相当于01背包里的 v[ i ].

背包的总体积要取预算最大的时候,即原来的x不停地加上每次有剩余优惠值的那些物品的【优惠值 - 现价】

代码附上~

#include <bits/stdc++.h> 
using namespace std;
typedef long long ll; 
const int maxn=4e5+10;
ll n,m,k,x,ans=0;
ll a[maxn],b[maxn],w[maxn],dp[maxn]; 
struct node{
	ll x,y;
}c[maxn];
int main() { 
	cin>>n>>x;
	ll pos=0;
	for(int i=0;i<n;i++){
		cin>>a[i]>>b[i]>>w[i];
		ll you=a[i]-b[i];
		b[i]-=you;
		if(b[i]<=0){
			ans+=w[i];
			x-=b[i];
		}else{
			node zz;
			zz.x=b[i];zz.y=w[i];
			c[++pos]=zz;
		}
	}
	for(int i=1;i<=pos;i++){
		for(int j=x;j>=c[i].x;j--){
			dp[j]=max(dp[j],dp[j-c[i].x]+c[i].y);
		}
	}
	cout<<dp[x]+ans<<endl;
	return 0;
}

那些没有花费的物品的w就直接加到ans里,
最后再加上ans就好。

【注意点】

  1. long long 放着还是保险点
  2. 空间开多少要斟酌一下,题目给的x是10000,但是算上优惠值,直接按照最大的优惠值算,也就是再加上500*500,大概是260000吧,我稍微开大了些,如果还是怕开小了可以再开大点。
发布了62 篇原创文章 · 获赞 0 · 访问量 637

猜你喜欢

转载自blog.csdn.net/weixin_44745441/article/details/105300732