挑战程序竞赛系列(9):2.4优先队列
2017-05-26 19:38
417 查看
挑战程序竞赛系列(9):2.4优先队列
详细代码可以fork下Github上leetcode项目,不定期更新。练习题如下:
POJ 3614: Sunscreen
POJ 2010: Moo University - Financial Aid
POJ 3614: Sunscreen
奶牛美容:有C头奶牛日光浴,每头奶牛分别需要minSPF_i和maxSPF_i单位强度之间的阳光。现有L种防晒霜,分别能使阳光强度稳定为SPF_i,其瓶数为cover_i。求最多满足多少头奶牛翻译参考:博文【POJ 3614 Sunscreen 题解 《挑战程序设计竞赛》】
思路:
防晒霜要从小到大排序,优先处理小的防晒霜。
奶牛按照minSPF从小到大排序,这样在所有符合某防晒霜的cow中,挑选maxSPF最小的。很直观,maxSPF越大,选择的余地越多。
代码为什么使用优先队列?
比如:奶牛的minSPF和maxSPF数据如下: a牛: 1 8 b牛: 2 7 c牛: 3 6 防晒霜如下: 4 2 那么我们应该选择第c头牛,如果还有防晒霜则再给b牛。因为a牛选择的余地最大,所以暂且放到最后再考虑。
代码如下:
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; } }
有个优化小细节,代码精简很多。
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的最小元素集合。
代码如下:
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; } }
相关文章推荐
- 挑战程序竞赛系列(56):4.4 双端队列(3)
- 挑战程序竞赛系列(54):4.4 双端队列(1)
- 挑战程序竞赛系列(1):2.3动态规划
- 挑战程序竞赛系列(3):2.3需要思考的动规
- 挑战程序竞赛系列(23):3.2折半枚举
- 挑战程序竞赛系列(26):3.5二分图匹配(1)
- 挑战程序竞赛系列(25):3.5最大权闭合图
- 挑战程序竞赛系列(36):3.3线段树和平方分割
- 挑战程序竞赛系列(21):3.2反转
- 挑战程序竞赛系列(20):3.2尺取法
- 挑战程序竞赛系列(31):4.5剪枝
- 挑战程序竞赛系列(5):2.1广度优先搜索
- 挑战程序竞赛系列(11):2.5最短路径
- 挑战程序竞赛系列(10):2.4并查集
- 挑战程序竞赛系列(22):3.2弹性碰撞
- 挑战程序竞赛系列(17):3.1最大化平均值
- 挑战程序竞赛系列(2):2.3优化递推关系式
- 挑战程序竞赛系列(8):2.1一往直前!贪心法(其他)
- 挑战程序竞赛系列(15):2.6快速幂运算
- 挑战程序竞赛系列(32):4.5 A*与IDA*