• poj 1064 Cable master


    二分

    题意:给出n条线段,以米的单位给出,小数点后两位(精确到厘米),要你对这些线段裁剪,裁剪出m条等长的线段,并且让这些线段尽可能长另外线段的长度不能小于1厘米,如果筹不够m条,输出0.00

    做法就是二分答案,但是二分的区间有讲究

    一开始我认为长度的上限应该是  min { len[i] },即最短的那条线段,后来才想到是错的,应该是max{ len[i] },因为有一点想当然了,认为裁剪线段,就是每条线段都要裁剪,其实不是的,并不是每条线段都要裁剪

    好像

    4 2

    2.00

    3.00

    4.00

    答案是2.00吗?不是的,应该是3.00,虽然3.00大于第一条线段的长度,那么就不要裁剪第1条线段,直接从第2,第3条线段开始裁剪,就能裁剪出2条3.00长度的线段

    另外,这题可以用浮点数的二分来写,但是基于题目的意思,完全可以转化为整数

    因为最后长度不能小于1厘米,而一开始给出的线段也是精确到厘米的,而答案也是要求精确到厘米的,那么为什么我们不一开始就把所有的数据都改成用厘米来表示呢?然后直接用整数来二分就可以避免掉所有精度的问题。所以一开始的二分区间就是[1,max{len[i]}] , 不要从0开始,完全没有比较,因为答案最小要为1

    最后一点,也是wa的地方,想了一阵子想明白了

    我们二分答案,得到一个长度l,然后用所有线段去除l,看能裁剪出多少条,然后统计条数的总和count

    然后就分类

    count < m,说明这个长度l太长,筹不够m条,所以要缩点长度l,去左半区间二分

    count = m,说明是一个合法的答案,记录,但是这样就可以了吗?可以跳出了吗?不是的,因为要找最大值,所以不能跳出,继续到右半区间二分

    count > m , 这是不是一个合法的答案?一开始没想清楚,认为不是合法的答案,其实是的!另外要到右半区间继续二分找一个更大的值

    下面的这个二分是错误的,就是因为count和m的判断出错

    首先count>m的情况是一个合法的答案,最要命的是,可能找不到满足条件的count == m,这能找到count > m

    例如

    3 5

    3.00

    3.00

    3.00

    答案是1.00,当答案是1.00的时候count=9 > 5 , 当答案为2,3的时候,count都无法等于m,根本无法更新答案

    因为想歪了一点,虽然题目要筹够m条,如果无法准确筹够m条的时间,只能缩短长度,筹出多余m条线段,因为裁剪多出来的线段,并不规定一定要用完

    while(low <= high)
            {
                int mid = (low + high) >> 1;
                int count = 0;
                for(int i=0; i<n; i++)
                {
                    int k = a[i] / mid;
                    count += k;
                }
                if(count == m)
                {
                    res = max(res , mid);
                    low = mid + 1;
                }
                else if(count > m)
                    low = mid + 1;
                else
                    high = mid - 1;
            }

    最后,用scanf读入数据,cin在G++会超时,在C++上没问题

    用整数来二分

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    using namespace std;
    #define N 10010
    #define MAX 10000000
    
    int a[N];
    
    int main()
    {
        int n,m;
        double len;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            int Max = 0;
            for(int i=0; i<n; i++)
            {
                scanf("%lf",&len);
                a[i] = len * 100;
                Max = max(Max , a[i]);
            }
            int low = 1 , high = Max;
            int res = 0;
            while(low <= high)
            {
                int mid = (low + high) >> 1;
                int count = 0;
                for(int i=0; i<n; i++)
                    count += a[i] / mid;
    
                if(count >= m)
                    res = max(res , mid) , low = mid + 1;
                else
                    high = mid - 1;
            }
            printf("%.2f\n",(double)res / 100.0);
        }
        return 0;
    }

    用浮点数二分,不推荐(没改scanf,交G++会超时)

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    const int N  = 10010;
    const double E = 0.0001;
    const double M = 0.01;
    
    double a[N];
    
    int main()
    {
        int n,m;
        double Max;
        while(cin >> n >> m)
        {
            Max = 0.0;
            for(int i=0; i<n; i++)
                cin >> a[i] , Max = max(Max,a[i]);
            double low = 0 , high = Max;
            while(high - low > E)
            {
                double mid = (low + high) / 2.0;
                int count = 0;
                for(int i=0; i<n; i++)
                {
                    double s = a[i] / mid;
                    int k = (int)s;
                    count += k;
                }
                if(count >= m)
                    low = mid;
                else
                    high = mid;
            }
            int tmp = high * 100;
            double res = (double)tmp * 0.01;
            printf("%.2f\n",res);
        }
        return 0;
    }
  • 相关阅读:
    scrapy之download middleware
    远程采集
    未能加载文件或程序集“Oracle.DataAccess, Version=4.112.2.0, Culture=neutral, PublicKeyTok”
    【转】如何解决C盘根目录无法创建或写入文件
    C#报算术运算导致溢出的错误
    【转】C# String 前面不足位数补零的方法
    【转】C# 使用正则表达式去掉字符串中的数字,或者去掉字符串中的非数字
    【转】Asp.Net页面生命周期
    【转】processOnServer
    【转】oracle的分析函数over
  • 原文地址:https://www.cnblogs.com/scau20110726/p/3131991.html
Copyright © 2020-2023  润新知