有点像背包,但是又不完全是
原因在于使用的物品有限制,使得物品的使用次序是未知的
这样显然无法扫一遍做背包
如果按照排序也是不对的,限制大的不一定先使用
若使用变为,这样中间错过了许多小型优惠劵,可能先使用中间的才更优
于是想到按照排序,直接做背包即可.
这样选择物品的顺序满足
如果只选择优惠券中的一个,那么顺序是无所谓的,背包会考虑到
如果需要同时选择物品,那么按照的顺序一定是可行的
反证法
设按照的顺序选可行得到
按照顺序选优惠券不可行得到
我们得到,也就是
而因为,移项得到
显然矛盾,证毕,不存在这种情况.
也就是说,按照这种方式排序不会错,直接做背包即可
#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; } }