前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >挑战程序竞赛系列(9):2.4优先队列

挑战程序竞赛系列(9):2.4优先队列

作者头像
用户1147447
发布2019-05-26 09:48:21
2900
发布2019-05-26 09:48:21
举报
文章被收录于专栏:机器学习入门机器学习入门

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://cloud.tencent.com/developer/article/1434776

挑战程序竞赛系列(9):2.4优先队列

详细代码可以fork下Github上leetcode项目,不定期更新。

练习题如下:

POJ 3614: Sunscreen

奶牛美容:有C头奶牛日光浴,每头奶牛分别需要minSPF_i和maxSPF_i单位强度之间的阳光。现有L种防晒霜,分别能使阳光强度稳定为SPF_i,其瓶数为cover_i。求最多满足多少头奶牛

翻译参考:博文【POJ 3614 Sunscreen 题解 《挑战程序设计竞赛》

思路:

  • 防晒霜要从小到大排序,优先处理小的防晒霜。
  • 奶牛按照minSPF从小到大排序,这样在所有符合某防晒霜的cow中,挑选maxSPF最小的。很直观,maxSPF越大,选择的余地越多。

代码为什么使用优先队列?

代码语言:javascript
复制
比如:奶牛的minSPF和maxSPF数据如下:
a牛: 1  8
b牛: 2  7
c牛: 3  6
防晒霜如下:
4  2
那么我们应该选择第c头牛,如果还有防晒霜则再给b牛。因为a牛选择的余地最大,所以暂且放到最后再考虑。

代码如下:

代码语言:javascript
复制
public class SolutionDay26_P3614 {

    public static void main(String[] args) {
        Scanner in= new Scanner(System.in);
        int C = in.nextInt();
        int L = in.nextInt();
        int[][] cows = new int[C][2];
        int[][] lotions = new int[L][2];
        for (int i = 0; i < C; i++){
            cows[i][0] = in.nextInt();
            cows[i][1] = in.nextInt();
        }
        for (int i = 0; i < L; i++){
            lotions[i][0] = in.nextInt();
            lotions[i][1] = in.nextInt();
        }
        System.out.println(solve(cows, lotions));
        in.close();
    }

    private static int solve(int[][] cows, int[][] lotions){
        Arrays.sort(cows, new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                return o1[0] !=  o2[0] ? o1[0] - o2[0] : o1[1] - o2[1];
            }
        });
        Arrays.sort(lotions, new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                return o1[0] - o2[0];
            }
        });

        Queue<int[]> queue = new PriorityQueue<>(new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                return o1[1] - o2[1];
            }
        });

        int cur = 0;
        int res = 0;
        for (int i = 0; i < lotions.length; i++){
            while (cur < cows.length && cows[cur][0] <= lotions[i][0]){
                queue.offer(cows[cur]);
                cur ++;
            }
            while (!queue.isEmpty() && lotions[i][1] != 0){
                if (queue.peek()[1] < lotions[i][0]){
                    queue.poll();
                }
                else{
                    res ++;
                    lotions[i][1]--;
                    queue.poll();
                }
            }
        }
        return res;
    }

}

有个优化小细节,代码精简很多。

代码语言:javascript
复制
while (!queue.isEmpty() && lotions[i][1] != 0){
    int max = queue.peek()[1]; queue.poll();
    if (max >= lotions[i][0]){
        res ++;
        lotions[i][1]--;
    }
}

POJ 2010: Moo University - Financial Aid

奶牛大学:奶大招生,从C头奶牛中招收N头。它们分别得分score_i,需要资助学费aid_i。希望新生所需资助不超过F,同时得分中位数最高。求此中位数。

思路:

用暴力的解法来做,有点类似累加和,来减少计算量。首先对奶牛的分数从小到大排序,所以只要知道当前坐标的0,i-1中N/2个元素之和的最小值和i+1,C的N/2个元素之和的最小值,就能通过暴力遍历来找到最大的中位数。

因为我们需要一直维护大小为N/2的最小元素集合,所以我们用堆来实现,这样,每次有新元素填入时,先offer进队列,然后再删除队首最大,就能始终保持大小为N/2的最小元素集合。

代码如下:

代码语言:javascript
复制
public class SolutionDay26_P2010 {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int N = in.nextInt();
        int C = in.nextInt();
        int F = in.nextInt();
        int[][] cast = new int[C][2];
        for (int i = 0; i < C; i++){
            cast[i][0] = in.nextInt();
            cast[i][1] = in.nextInt();
        }
        System.out.println(solve(cast, N, F));
        in.close();
    }

    private static int solve(int[][] cast, int N, int F){
        Arrays.sort(cast, (a, b) -> (a[0] - b[0]));

        int[] lower = new int[cast.length];
        int[] upper = new int[cast.length];
        Arrays.fill(lower, 1<<30);
        Arrays.fill(upper, 1<<30);
        int half = N / 2;
        {
            Queue<Integer> queue = new PriorityQueue<>((a,b) -> (b-a));
            int total = 0;
            for (int i = 0; i < cast.length; i++){
                if (queue.size() == half){
                    lower[i] = total;
                    queue.offer(cast[i][1]);
                    total += cast[i][1];
                    total -= queue.poll();
                }else{
                    total += cast[i][1];
                    queue.offer(cast[i][1]);
                }

            }
        }

        {
            Queue<Integer> queue = new PriorityQueue<>((a,b) -> (b-a));
            int total = 0;
            for (int i = cast.length - 1; i >=0; i--){
                if (queue.size() == half){
                    upper[i] = total;
                    queue.offer(cast[i][1]);
                    total += cast[i][1];
                    total -= queue.poll();
                }else{
                    total += cast[i][1];
                    queue.offer(cast[i][1]);
                }

            }
        }

        int res = -1;
        for (int i = cast.length-1; i >= 0; i--){
            if (lower[i] + cast[i][1] + upper[i] <= F){
                res = cast[i][0];
                break;
            }
        }
        return res;
    }
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017年05月26日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 挑战程序竞赛系列(9):2.4优先队列
    • POJ 3614: Sunscreen
      • POJ 2010: Moo University - Financial Aid
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档