挑战程序竞赛系列(17):3.1最大化平均值
2017-06-23 11:51
435 查看
挑战程序竞赛系列(17):3.1最大化平均值
详细代码可以fork下Github上leetcode项目,不定期更新。练习题如下:
POJ 2976: Dropping tests
POJ 3111: K Best
POJ 2976: Dropping tests
01分数规划,具体可以参考博文http://www.cnblogs.com/perseawe/archive/2012/05/03/01fsgh.html,写的非常详细且通俗易懂。我的认识:中学里学过二分法求函数零点,其实该代码模拟的就是这种求解过程,所以只要写出目标函数,零点不难求。
接着就得到了求和式:
∑i=1n(ai−l⋅bi)≥0
要删除k个物品,当然选择贡献最小的,所以按照ai−l⋅bi排序,选择n-k个物品,排除其余贡献较小的k个物品。
代码如下:
static class Pair implements Comparable<Pair>{ int a; int b; @Override public int compareTo(Pair o) { double ocmp = o.a - L * o.b; double tcmp = this.a - L * this.b; return ocmp == tcmp ? 0 : (ocmp > tcmp) ? 1 : -1; } } static Pair[] p; static double L; static int k; static int n; public static void main(String[] args) throws IOException { Scanner in = new Scanner(System.in); while (true){ n = in.nextInt(); k = in.nextInt(); if (n == 0 && k == 0) break; p = new Pair ; for (int i = 0; i < n; ++i){ p[i] = new Pair(); p[i].a = in.nextInt(); } for (int i = 0; i < n; ++i){ p[i].b = in.nextInt(); } double lf = 0; double rt = 1; while (Math.abs(rt -lf) > 1e-4){ double mid = (lf + rt) / 2; if (!valid(mid)) rt = mid; else lf = mid; } System.out.printf("%.0f\n",lf * 100); } } public static boolean valid(double mid){ L = mid; Arrays.sort(p); double sum = 0; for (int i = 0; i < n - k; ++i){ sum += (p[i].a - L * p[i].b); } return sum > 0; }
POJ 3111: K Best
和上一题一个思路,但此题精度要求要高很多,按照上一题的while循环,WA了,测了下,大概循环14次左右,而此题循环50次,可以达到0.000000001的精度。注意记录下下标。代码如下:
static class Pair implements Comparable<Pair>{ int a; int b; int id; @Override public int compareTo(Pair o) { double that = o.a - L * o.b; double thiz = this.a - L * this.b; return that == thiz ? 0 : (that > thiz) ? 1 : -1; } } static double L; static Pair[] p; static int N; static int K; public static void main(String[] args) throws IOException { Scanner in = new Scanner(System.in); N = in.nextInt(); K = in.nextInt(); p = new Pair ; ans = new int[K]; for (int i = 0; i < N; ++i) p[i] = new Pair(); double max = 0; for (int i = 0; i < N; ++i){ p[i].a = in.nextInt(); p[i].b = in.nextInt(); p[i].id = i + 1; max = Math.max(max, p[i].a / (p[i].b * 1.0 )); } double lf = 0.0; double rt = max; for (int i = 0; i < 50; ++i){ double mid = (lf + rt) / 2; if (!valid(mid)) rt = mid; else lf = mid; } for (int i = 0; i < K; ++i) ans[i] = p[i].id; StringBuilder sb = new StringBuilder(); Arrays.sort(ans); for (int i : ans){ sb.append(i + " "); } System.out.println(sb.toString().trim()); } static int[] ans; public static boolean valid(double mid){ L = mid; Arrays.sort(p); double sum = 0.0; for (int i = 0; i < K; ++i){ sum += (p[i].a - L * p[i].b); } return sum > 0; }
相关文章推荐
- 挑战程序竞赛系列(16):3.1最大化最小值
- 挑战程序竞赛系列(18):3.1查找第k大的值
- 挑战程序竞赛系列(19):3.1最小化第k大的值
- 挑战程序竞赛系列(31):4.5剪枝
- 挑战程序竞赛系列(36):3.3线段树和平方分割
- 挑战程序竞赛系列(23):3.2折半枚举
- 挑战程序竞赛系列(22):3.2弹性碰撞
- 挑战程序竞赛系列(32):4.5 A*与IDA*
- 挑战程序竞赛系列(25):3.5最大权闭合图
- 挑战程序竞赛系列(15):2.6快速幂运算
- 挑战程序竞赛系列(14):2.6素数
- 挑战程序竞赛系列(38):4.1模运算的世界(1)
- 挑战程序竞赛系列(34):3.2坐标离散化
- 挑战程序竞赛系列(5):2.1广度优先搜索
- 挑战程序竞赛系列(3):2.3需要思考的动规
- 挑战程序竞赛系列(9):2.4优先队列
- 挑战程序竞赛系列(35):3.3Binary Indexed Tree
- 挑战程序竞赛系列(2):2.3优化递推关系式
- 挑战程序竞赛系列(7):2.1一往直前!贪心法(区间)
- 挑战程序竞赛系列(20):3.2尺取法