• UVALive 3507:Keep the Customer Satisfied(贪心 Grade C)


    VJ题目链接

    题意:

    知道n(n <= 8e6)个工作的完成所需时间q和截止时间d,你一次只能做一个工作。问最多能做多少工作?

    思路:

    首先很像贪心。观察发现如下两个贪心性质:

    1)一定存在一个最优方案,使得截止时间靠后的工作一定比截止时间靠前的工作迟完成(如果完成的话)

    证明:

    若工作i, j 有 d[i] > d[j]。假设我们现在有一个工作方案,使得i工作在j工作之前完成。

    如  ..., i , ... , j , ...

    记做 preI, i, midIJ, j, afterJ

    此时将这个工作方案的i移动到j后面一个完成,其他不动。

    则变成 preI , midIJ , j , i , afterJ

    如此交换对 preI和afterJ 部分不会有影响。

    对于midIJ部分,由于i的抽出,使得整体完成时间前移,所以不会导致结果更差。

    对于j,原先在截止时间内,现在抽出了i,所以一定也在截止时间内。

    对于i,因为d[i] > d[j],而现在i的完成时间等同于原先j的完成时间,所以i也一定能完成。

    所以这个交换方案不会使得结果更差。

    至于会不会变得更好,没有证明,感觉会吧~~迟一点的可以拖一下嘛。。。

    2)若存在一种方案,使得 d[i] < d[j] 且 q[i] > q[j] 且选择了i而没有选择j, 则一定可以用j代替i。

    证明:略。

    所以采用如下贪心策略:

    按d从小到大排序,然后依次放入。若放入后爆炸,则看一下前面最大的那个,如果最大的比这个大,踹走后,把这个放进去。

    【注:本题证明不完备。可能有问题。如有发现,多谢指正】

    坑点:忘记两组数据之间有空行。。。

    代码:

    #include <cstdio>
    #include <cstring>
    #include <queue>
    #include <algorithm>
    using namespace std;
    
    #define N 800100
    
    struct Work{
        int q, d;
        void read() {
            scanf("%d%d", &q, &d);
        }
        bool operator < (const Work &b) const {
            if (d != b.d) return d < b.d;
            return q < b.q;
        }
    }works[N];
    
    priority_queue<int> que;
    
    int main() {
        int t;
        scanf("%d", &t);
        int _ = 0;
        while (t--) {
            !_++?:puts("");
            int n;
            scanf("%d", &n);
            for (int i = 0; i < n; i++) {
                works[i].read();
            }
    
            sort(works, works+n);
    
            while (!que.empty()) que.pop();
            int now = 0;
            int cnt = 0;
            for (int i = 0; i < n; i++) {
                if (now + works[i].q <= works[i].d) {
                    now += works[i].q;
                    que.push(works[i].q);
                    cnt++;
                } else {
                    if (!que.empty() && works[i].q < que.top()) {
                        now -= que.top();
                        now += works[i].q;
                        que.pop();
                        que.push(works[i].q);
                    }
                }
            }
            printf("%d
    ", cnt);
        }
        return 0;
    }
  • 相关阅读:
    Android的selector,背景选择器
    JAVA静态和非静态内部类
    Android应用资源--之属性(Attribute)资源
    contentprovider的学习实例总结
    转:Android 2.3 代码混淆proguard技术介绍
    忘掉旋转,利用2-3-4树,学习红黑树
    ios 定位获取当前位置信息
    地图相关
    mac下,svn配置
    NimBus一个好的开发框架
  • 原文地址:https://www.cnblogs.com/shinecheng/p/4000461.html
Copyright © 2020-2023  润新知