NYG的背包 (贪心)

来源:互联网 发布:php urldecode解码 编辑:程序博客网 时间:2024/05/17 02:34

9.19

题解

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define LL long longusing namespace std;const int N = 1e5+4, INF = 0x3f3f3f3f;struct Node {    LL aa, bb, cc;    friend bool operator <(const Node &p, const Node &q) {        if(p.cc>=0 && q.cc>=0) return p.aa < q.aa;        if(p.cc<0 && q.cc<0) return p.bb > q.bb;        return p.cc>=0;    }}aa[N];int n,T;LL V;inline int read() {    int x=0; char cc=getchar();    while (cc<'0'||cc>'9') cc=getchar();    while (cc>='0'&&cc<='9') x=x*10+cc-'0',cc=getchar();    return x;}int main() {    freopen("backpack.in","r",stdin);    freopen("backpack.out","w",stdout);    T = read();    while (T--) {        n = read(), V = read();        for(register int i=1; i<=n; ++i)            aa[i].aa = read(), aa[i].bb = read(), aa[i].cc = aa[i].bb - aa[i].aa;        sort(aa+1, aa+n+1);        bool flag = true;        for(register int i=1; i<=n; ++i) {            if(V < aa[i].aa) {flag = false; break;}            V += aa[i].cc;        }        puts(flag ? "Yes" : "No");    }    return 0;}

此题很有复习价值,本题中有几个点重点:

【1】 对于可行问题要往贪心方向思考

【2】 在想贪心方案是需要严格证明,宁可画上一定时间(但要控制再半小时以内)去证明正确性 , 找反例

【3】 在想贪心情况时 , 要落到实处 ,若觉得一个策略不对则需要通过题目特性落到实处看其是否正确;找反例时先感性想想反例出现情况,在去构造对应数据看是否能否定当前结论

在解决此题时 , 由于放入体积与增加体积,而且题目问题是是否可解,可使人想到贪心;

而贪心策略中,由于要是其放得下,所以可以想到先放有贡献(增加体积)的情况 , 然后猜测是贪心顺序,以a排序?b排序?还是b-a?此时发现它最后加完的体积是一个定值 , 而其体积也在不断增加,那么应该是a越大的放到越后面能跟保险的放下,然而是否会有反例,根据其特性:v会应为b - a > 0 而不断增大,显而易见策略正确;

而此题头疼的是b - a < 0 时的策略 : 还是按照上面所述的思路 , a?,b?,b-a?,按照从大到小?从小到大?貌似从正面不好想,但有个性质时确定的:

最后的体积为定值

那么从次特性思考,倒着来想:
最后的状态是:

V + b1 + b2 + b3 + … + bn >= a1 + a2 + a3 + … + an

那么最后一次选择便是选择先将左式减去对于的b , 在不等式成立的情况下在减去对应得a ,由于后面加上的是b - a < 0 , 那么每次减去一组对应的a,b时左式减右式的值会越来越大 , 所以只要保证每次删的b最小,时左式减小的尽量少,那么等式则月容易成立,所以嘛。。。反过来想 , 不就是。。。以b为标准从大到小排序。。。
那么全程的贪心策略则出来了:
对于 a - b > 0 的情况 以a为标准从小到大排序
对于 a - b < 0 的情况 以b为标准从大到小排序

原创粉丝点击