二分入门——poj 1064 cable master

来源:互联网 发布:全民奇迹挂机软件 编辑:程序博客网 时间:2024/05/29 03:23

这道题是一道很标准的二分入门题,从这道题中可以感受到二分法在精度问题上强大的处理能力,这个题若是要用贪心水……也是可以的,但是用哪个题练贪心不好,非要用这么好的二分题练,神犇的想法无法理解。
先给原题:

Problem Description
Inhabitants of the Wonderland have decided to hold a regional programming contest. The Judging Committee has volunteered and has promised to organize the most honest contest ever. It was decided to connect computers for the contestants using a “star” topology - i.e. connect them all to a single central hub. To organize a truly honest contest, the Head of the Judging Committee has decreed to place all contestants evenly around the hub on an equal distance from it.

To buy network cables, the Judging Committee has contacted a local network solutions provider with a request to sell for them a specified number of cables with equal lengths. The Judging Committee wants the cables to be as long as possible to sit contestants as far from each other as possible.

The Cable Master of the company was assigned to the task. He knows the length of each cable in the stock up to a centimeter, and he can cut them with a centimeter precision being told the length of the pieces he must cut. However, this time, the length is not known and the Cable Master is completely puzzled.

You are to help the Cable Master, by writing a program that will determine the maximal possible length of a cable piece that can be cut from the cables in the stock, to get the specified number of pieces.

Input
The input consists of several testcases. The first line of each testcase contains two integer numbers N and K, separated by a space. N (1 ≤ N ≤ 10000) is the number of cables in the stock, and K (1 ≤ K ≤ 10000) is the number of requested pieces. The first line is followed by N lines with one number per line, that specify the length of each cable in the stock in meters. All cables are at least 1 centimeter and at most 100 kilometers in length. All lengths in the input are written with a centimeter precision, with exactly two digits after a decimal point.

The input is ended by line containing two 0’s.

Output
For each testcase write to the output the maximal length (in meters) of the pieces that Cable Master may cut from the cables in the stock to get the requested number of pieces. The number must be written with a centimeter precision, with exactly two digits after a decimal point.

If it is not possible to cut the requested number of pieces each one being at least one centimeter long, then the output must contain the single number “0.00” (without quotes).

Sample Input

4 11
8.02
7.43
4.57
5.39
0 0

Sample Output

2.00

再给个题目翻译:

题意:

给你n条电缆,让你把它们分成k段,求每段最长能分成多长。

输入:

一个n一个k,n个电缆的长度(二位小数)。

输出:

最长长度。

这个题我们首先看到输入,就明白,要用到double变量,这里样例有一个神奇的精度,如果直接用double做会爆炸,2.01卡得挺挺的,所以要在输出的时候乘一百再除以一百。

再说到算法上来,这个题能够想到的二分策略有两个:通过最小电缆直接二分,用最优情况直接二分。
前者在某些特殊情况下会挂,所以我们采用后者。
附上代码(注释详解算法):

#include<stdio.h>#include<cmath>#include<string.h>#include<algorithm>#include<iostream>using namespace std;const int maxn=10001;const double _oo=1e-5;//常量:精度判断 int n,k;double a[maxn],sum;int main(){    while(scanf("%d%d",&n,&k)==2&&n&&k)    {        sum=0;    //先赋初值为零        for(int i=0;i<n;i++)        {            scanf("%lf",&a[i]);//输入每一组数据             sum+=a[i];// 求一下所有电缆长度的和         }        sum=sum/k;//这是最优情况,就是所有的电缆长度总和除以k为切的最大值。        double h=0,t=sum;//二分套路         while(fabs(h-t)>_oo)//判断条件,只要二分的结果一个达不到一个精度就继续二分。        {               int sie=0;//这个变量用来判断当前的切的长度除每个电缆长是否满足k             double mid=(h+t)/2;              for(int i=0;i<n;i++)              {                 sie+=(int)(a[i]/mid); //把这个长度用每一个电缆都试一遍,得到一个值             }              if(sie>=k)//如果这个值大于等于k,那说明切小了,就让这个所切的值作为h,继续二分                 h=mid;            else                   t=mid;         }        printf("%.2f\n",int(t*100)*0.01);//精度注意 ,输出的是t注意。     }    return 0;}

这个题有一个非常有意思的地方,那就是判断常量的精度,我采用的1e-5,在这道题的数据上能过,但是这个跟1e-4,1e-3情况都不同,分别用了94ms,125ms,141ms。
按照常理来说判断精度的数字越小时间越长才对,这里竟然反了过来,真是神奇。
我试了一下1e-9看看会不会起飞,但是时间又慢到了141ms。
得出结论:这是玄学……

0 0