牛客小白月赛35 J.溪染的优惠券(贪心01背包)

Posted issue是fw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了牛客小白月赛35 J.溪染的优惠券(贪心01背包)相关的知识,希望对你有一定的参考价值。

LINK

有点像 01 01 01背包,但是又不完全是

原因在于使用的物品有限制,使得物品的使用次序是未知的

这样显然无法扫一遍做 01 01 01背包

如果按照 a i a_i ai排序也是不对的,限制大的不一定先使用

若使用变为 k − b i k-b_i kbi,这样中间错过了许多小型优惠劵,可能先使用中间的才更优

于是想到按照 a i − b i a_i-b_i aibi排序,直接做 01 01 01背包即可.

这样选择物品的顺序满足 a i − b i > a j − b j a_i-b_i>a_j-b_j aibi>ajbj

如果只选择 i , j i,j i,j优惠券中的一个,那么顺序是无所谓的, 01 01 01背包会考虑到

如果需要同时选择 i , j i,j i,j物品,那么按照 i , j i,j i,j的顺序 d p dp dp一定是可行的

反证法

设按照 j , i j,i j,i的顺序选可行得到 k > = a j & & k − b j > = a i k>=a_j\\&\\&k-b_j>=a_i k>=aj&&kbj>=ai

按照 i , j i,j i,j顺序选优惠券不可行得到 k > = a i & & k − b i < a j k>=a_i\\&\\&k-b_i<a_j k>=ai&&kbi<aj

我们得到 k > = a i + b j & & k < a j + b i k>=a_i+b_j\\&\\&k<a_j+b_i k>=ai+bj&&k<aj+bi,也就是 a j + b i > a i + b j a_j+b_i>a_i+b_j aj+bi>ai+bj

而因为 a i − b i > a j − b j a_i-b_i>a_j-b_j aibi>ajbj,移项得到 a i + b j > a j + b i a_i+b_j>a_j+b_i ai+bj>aj+bi

显然矛盾,证毕,不存在这种情况.

也就是说,按照 i , j i,j i,j这种方式排序不会错,直接做 01 01 01背包即可

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e4+10;
int n,k,vis[maxn],s[maxn],f[maxn];
typedef pair<int,int>p;
p a[maxn];
bool com(p a,p b)
{
	if( a.first-a.second==b.first-b.second )	return a.first<b.first;
	return a.first-a.second>b.first-b.second;
}
int main()
{
	cin >> n >> k;
	for(int i=1;i<=n;i++)	cin >> a[i].first >> a[i].second;
	f[k] = 1;
	sort( a+1,a+1+n,com );
	for(int i=1;i<=n;i++)
	for(int j=a[i].first;j<=k;j++)
		f[j-a[i].second] |= f[j];
	int ans = k;
	for(int i=0;i<=k;i++)
		if( f[i] ){	cout << i; return 0; }
}

以上是关于牛客小白月赛35 J.溪染的优惠券(贪心01背包)的主要内容,如果未能解决你的问题,请参考以下文章

牛客小白月赛53 E.Calling(贪心)

牛客小白月赛35 G.反·反爬虫函数(随机....)

牛客小白月赛37部分题解

牛客白月赛23题解

牛客小白月赛#67(A-D)

牛客小白月赛#69(A-E)