zoukankan      html  css  js  c++  java
  • 题解【luoguP4053 bzojP1029 [JSOI2007]建筑抢修】

    洛谷题链
    bzoj题链


    PS:

    • (t_i) : 在什么时候建筑 (i) 自爆

    • (a_i) : 修复 (i) 所花时间


    题解
    算法:贪心+堆维护

    贪心策略:

    • 直接按 (t) 贪心?显然不行。
    • 那我们考虑先按 (t) 贪心,中途再更改。
    • (t) 从小到大排序之后,开始轮流遍历每个建筑。
    • 如果中途某个建筑 (i) 无法在 (t_i) 的时间内修复,那么在先前选择修复的建筑中拿出 (a_j) 最大的 (j) 号建筑。若 (a_i < a_j),则放弃 (j) 转而修 (i)(主思路)

    策略证明:

    • 若第 (i) 号出现时间不足,那么前 (i) 个建筑中最多修复 (i-1) 个建筑
    • 则我们必然选择 (a_i) 较小的前 (i-1) 个建筑,给后面的修复留下更多的时间

    实现方法:

    • 使用堆来维护选择的建筑中 (a_i) 最大的。
    • 这里我用的是STL中的优先队列。
    • 至于堆和优先队列,不会的童鞋请自行学习

    实际代码:

    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #include <algorithm>
    #include <queue>
    #define MAXN 200200
    using namespace std;
    
    int n;
    int T;//T指遍历时经过了多久时间
    int ans;
    struct node
    {
        int w; //这个是题解中的ai
        int t;
    }a[MAXN];
    priority_queue<int> Q;//优先队列
    
    bool cmp (node x, node y)
    {
        return x.t < y.t;//按t从小到大排序
    }
    int main()
    {
        scanf("%d", &n);
        for(int i = 1; i <= n; i++)
            scanf("%d%d", &a[i].w, &a[i].t);
        sort(a + 1, a + n + 1, cmp);
        for(int i = 1; i <= n; i++)
        {
            if(T + a[i].w > a[i].t)//如果无法修复此楼
            {
                if(a[i].w < Q.top())//ai < aj
                {
                    T -= Q.top();//注意这里要减掉
                    Q.pop();
                    Q.push(a[i].w);
                    T += a[i].w;
                }
            }
            else 
            {
                Q.push(a[i].w);
                ans++;
                T += a[i].w;
            }
        }
        printf("%d
    ", ans);
        return 0;
    }
    
    蒟蒻一枚
  • 相关阅读:
    标准部件工具箱概述
    从数据库和文件夹中读取图片并且resize
    控件的Lookup
    分隔字符串并以List返回(strSplit函数)
    窗体中的选中数据传递给报表
    对筛选之后的grid进行求和统计
    动态添加图片控件例子
    利用CSV文件导入数据的例子
    调用打开文件的对话框
    ax设置数据源的操作
  • 原文地址:https://www.cnblogs.com/acfunction/p/8857107.html
Copyright © 2011-2022 走看看