牛客小白月赛35 J.溪染的优惠券(贪心01背包)
Posted issue是fw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了牛客小白月赛35 J.溪染的优惠券(贪心01背包)相关的知识,希望对你有一定的参考价值。
有点像 01 01 01背包,但是又不完全是
原因在于使用的物品有限制,使得物品的使用次序是未知的
这样显然无法扫一遍做 01 01 01背包
如果按照 a i a_i ai排序也是不对的,限制大的不一定先使用
若使用变为 k − b i k-b_i k−bi,这样中间错过了许多小型优惠劵,可能先使用中间的才更优
于是想到按照 a i − b i a_i-b_i ai−bi排序,直接做 01 01 01背包即可.
这样选择物品的顺序满足 a i − b i > a j − b j a_i-b_i>a_j-b_j ai−bi>aj−bj
如果只选择 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&&k−bj>=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&&k−bi<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 ai−bi>aj−bj,移项得到 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背包)的主要内容,如果未能解决你的问题,请参考以下文章