2017年浙江中医药大学大学生程序设计竞赛(重现赛)D - CC的神奇背包
题目描述
cc最近收到了好多礼物,对着满地大小不一的礼物,她想要一个包来装,于是dd就掏出了一个会说话的神奇背包给cc装礼物。
cc为了一次性装尽可能多的礼物,于是跟这个背包定下了一个规则,对每个礼物,背包会给出它对这件礼物的喜爱程度,背包越喜欢这个礼物,它就会越开心,越开心,它就会扩大自己的容量。
于是问题就变成了这样:每个礼物都有自己的体积ai,背包也会给出它对这些礼物的喜爱程度bi,并且为了方便cc计算,背包告诉cc,喜爱程度bi就是这件物体放进背包,背包后会扩大的体积。
那么现在cc想知道,对这一地的礼物,有没有某种放的顺序,可以一次性把所有礼物都放进包里?
当然,物体要先放进背包,背包才会扩大自己的体积
比如当前背包的剩余体积为2,礼物的体积为3,喜爱程度为4,也是不能放进背包的。
cc为了一次性装尽可能多的礼物,于是跟这个背包定下了一个规则,对每个礼物,背包会给出它对这件礼物的喜爱程度,背包越喜欢这个礼物,它就会越开心,越开心,它就会扩大自己的容量。
于是问题就变成了这样:每个礼物都有自己的体积ai,背包也会给出它对这些礼物的喜爱程度bi,并且为了方便cc计算,背包告诉cc,喜爱程度bi就是这件物体放进背包,背包后会扩大的体积。
那么现在cc想知道,对这一地的礼物,有没有某种放的顺序,可以一次性把所有礼物都放进包里?
当然,物体要先放进背包,背包才会扩大自己的体积
比如当前背包的剩余体积为2,礼物的体积为3,喜爱程度为4,也是不能放进背包的。
输入描述:
输入包含多组数据,第一行为一个整数T(1<=T<=20)
每组数据第一行包含两个整数n,v(1<=n,v<=1000)表示共有n个礼物,背包一开始的体积为v
接下去的n行每行包含两个整数ai,bi(1<=ai,bi<=1000)表示每个礼物的体积ai与背包对这件礼物的喜爱程度bi
1 <= T <= 20
1 <= n, v <= 100000
1 <= ai, bi <= 100000
输出描述:
若存在一种放礼物的顺序可以让cc把所有礼物放进背包,则输出"yes"否则输出"no"(引号不包含在内)
示例1
输入
1 4 2 1 2 2 1 3 1 2 3
输出
yes
题解
贪心。
先把能放进去的且能扩大容量或者保持容量不变的那些都加进去。
加完之后必然是最大容量了。这个时候再慢慢塞减少容量的那些东西即可。细节注意一下。
#include <bits/stdc++.h> using namespace std; const int maxn = 100000 + 10; int T; int n; long long v; struct X { long long a, b; }p[maxn]; bool cmp(const X&a, const X&b) { return a.a < b.a; } bool cmp2(const X&a, const X&b) { return a.b < b.b; } int main() { scanf("%d", &T); while(T --) { scanf("%d%lld", &n, &v); for(int i = 1; i <= n; i ++) { long long x, y; scanf("%lld%lld", &x, &y); p[i].a = x; p[i].b = y - x; } int sum = 0; sort(p + 1, p + 1 + n, cmp); for(int i = 1; i <= n; i ++) { if(p[i].b >= 0 && p[i].a <= v) { v = v + p[i].b; sum ++; } } if(sum == n) { printf("yes\n"); continue; } int flag = 1; for(int i = 1; i <= n; i ++) { if(p[i].a > v) { flag = 0; break; } } if(flag == 0) { printf("no\n"); continue; } sort(p + 1, p + 1 + n, cmp2); for(int i = n; i >= 1; i --) { if(p[i].b >= 0) continue; if(p[i].a <= v) { v = v + p[i].b; } else { flag = 0; break; } } if(flag == 0) { printf("no\n"); continue; } printf("yes\n"); } return 0; }