zoukankan      html  css  js  c++  java
  • ZOJ 1601. Integer Approximation

        ZOJ 1601:Integer Approximation

        链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1601

        题意:对于一个给定的浮点数A(0.1 <= A <= 10)和一个最大值 L(1 <= L <= 100,000),在 1 到 L  之间找出最佳的两个整数 N 和 D (1<= N, D <= L),使得 N / D 的结果和 A 最接近(即 | A - N / D | 最小)。例如对于圆周率 pi = 3.14159265358979,在 1 到 10000 之间 355 / 133 的结果最接近 pi 。

        分析:从直观上来看,除了“穷举式”的依次寻找,似乎并没有什么特别的捷径可寻。而且题目中对于 L 的值较小,不会超过 10w,这也暗示我们解法就是在这个范围内做一个完全搜索。

        显然如果除法的结果是相同的,则整数越小越好,因此我们应从小到大搜索,这样后续的较大的等效除法就不会覆盖前面的。注意起始搜索点要根据 A 和 1 之间的关系而定。例如如果 A < 1,这时候 N < D。因此应该先令 N = 1。反过来如果 A > 1,应该先令 D = 1。为了效率,我们应该以比较小的那个数字为基础进行逐个搜索,因为另一个数字计算后具有放大作用。所以用比较小的数字搜索的话,循环次数会小于基于比较大的数字进行搜索。但下面的代码,为了简单起见,一律基于 D 进行逐个搜索,并没有区别对待。

        例如如果 A = 0.1,则我们从 N = 1, D = 10 开始搜索,基于 D 进行累加,N = D * 0.1 会变化的很慢,将降低效率。因此这时候应该基于 N 搜索即累加 N 。如果调整 D 的步进值为 max( 1, (int)(1/A + 0.5) ),则要从数学上分析如何取整的问题,也就是对 D 采用一个固定的步进值和基于 N 搜索未必是等价的(因为 D 作为整数,和 N/A 之间存在误差),比较麻烦。 

        下面的代码中,y / x 是我们要探查的当前整数除法,即 y 对应的是 N,x 对应的是 D。err 是 y / x 和浮点数 A 之间的相对误差。在选取第一对整数时,务必要注意 L 的限制。例如如果 A = 0.1,则不考虑 L 我们选取的第一对整数应该是 1/10。但是如果 L = 5,那么 1/10 是不可能选到的,第一对整数就应该是 1 / 5。

    zoj1601
    #include <stdio.h>
    #include <math.h>
    
    void FindResult(double A, int L, int* pN, int* pD)
    {
        double minerr = 100000, err;
        int x, y;
    
        if(A >= 1)
        {
            x = 1;
            y = (int)(x * A + 0.5);
            if(y > L) y = L;
        }
        else
        {
            y = 1;
            x = (int)(y / A + 0.5);
            if(x > L) x = L;
        }
        while(x <= L && y <= L)
        {    
            err = fabs(x * A - y);
            if(err < minerr)
            {
                *pN = y;
                *pD = x;
                minerr = err;
            }
            ++x;
            y = (int)(x * A + 0.5);
        }
    }
    
    int main(int argc, char* argv[])
    {
        double A;
        int L, N, D;
        while(scanf("%lf %ld", &A, &L) != EOF)
        {
            FindResult(A, L, &N, &D);
            printf("%ld %ld\n", N, D);
        }
        return 0;
    }
  • 相关阅读:
    select选择框去掉默认的下拉箭头
    网站怎么添加ico小图标
    js实现逐字打印效果,文本逐字显示
    jQuery实现消息列表循环垂直向上滚动
    滤镜图片变黑白+图片模糊
    多选下拉框(select 下拉多选)
    JavaScript 数组相关基础方法
    h5+ IOS App中判断本地文件是否存在 plus.io.resolveLocalFileSystemURL()
    h5+ IOS App中取消视频默认全屏播放
    C# 多线程与队列操作小练刀
  • 原文地址:https://www.cnblogs.com/hoodlum1980/p/2533063.html
Copyright © 2011-2022 走看看