zoukankan      html  css  js  c++  java
  • ZOJ 1608. Two Circles and a Rectangle

        地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1608

        题意:给你两个圆形(半径分别为 r1 、r2 )和一个矩形(矩形边长为 a 和 b),判断两个圆是否能放于矩形内。其中 a, b, r1, r2 都是浮点数。

        分析:考虑两个圆能放入的一个最基本的必要条件就是:半径最大的圆至少要能放入,那么小圆自然也能放入,即 min( a,  b ) >= max( r1, r2 ) * 2;

        接下来分析能否放入的临界点。假设矩形的长边是 a,短边是 b,大圆半径是 r1, 小圆半径是 r2,满足上述条件时( b >= r1 * 2 ),r2 很小的情况可以不必考虑。

        另 b 略大于 r1 * 2,设想右侧短边是一个可以滑动的挡板,从远处向左侧短边滑动。 当 a 非常大时,两个圆靠近成相切状态,两个圆可以同时与底边相切(但这不是最节省空间状态)。当矩形向内收缩时,达到下图所示状态时(两个圆分别和矩形相对的边相切,即理想状态下矩形每条边只和一个圆相切,只有一个切点),将不能继续收缩,即到达临界点:

        

        我们也可以从另一个角度理解,假设上图是一个内壁十分光滑的容器(可以是集装箱或者汽油桶)的截面,底部的宽度固定为 a,且略大于大圆(表面光滑的圆柱体或者球体)直径(2*r1),先把大圆放入容器,再把小圆放入,则必然因为重力作用,小圆把大圆挤向容器的另一侧,稳定于上述图形的状态。

        设图中红色直角三角形的两个直角边边分别为 x,y,斜边为 z,则:

        z = r1 + r2;

        x = a - z;

        y = b - z;

        其中斜边 z 是两圆相切时的圆心距离,可看作是固定的。直角边 x、y 主要取决于矩形边长。因此当 z^2 <= x^2 + y^2 时意味着矩形足够大,可以放入矩形内。否则不能放入。下面的代码中函数 judge 的返回值含义看做是 BOOL 类型,表示是否可放入。

    zoj1608
    #include <math.h>
    #include <stdio.h>
    
    int judge(double a, double b, double r1, double r2)
    {
        double maxside = a > b ? a : b;
        double minside = a < b ? a : b;
        double maxR = r1 > r2 ? r1 : r2;
        double minR = r1 < r2 ? r1 : r2;
    
        if(minside < maxR * 2)
            return 0;
    
        double z = r1 + r2;
        double x = a - z;
        double y = b - z;
        
        if(x * x + y * y < z * z)
            return 0;
        else
            return 1;
    }
    
    int main(int argc, char* argv[])
    {
        double a, b, r1, r2;
        while(scanf("%lf %lf %lf %lf", &a, &b, &r1, &r2) != EOF)
        {
            if(judge(a, b, r1, r2)) printf("Yes\n");
            else printf("No\n");
        }
        return 0;
    }

        最后,题目中的“You can safely assume x < y, where x and y are float-point numbers, if x < y + 0.01.” 这句话是什么意思呢,其实就是让你不必关注浮点数的大小比较,其两个浮点数的大小关系将是非常显著的。我推测出题者的意思就是测试数据的浮点数关系不是大于就是小于(明显不能放入或明显能放入),而不会出现非常接近(非常靠近能否放入的临界点),例如 1.00001 和 1.00002 这样的让人比较纠结的情况。所以上面的代码中不必考虑浮点计算和比较时的精度问题,即分析和代码中的所有等于号“=”应该都是可以去掉的。如果两个浮点数非常接近,例如给出一个矩形的边分别是 5.0000 和 4.9999,满足 5.0000 < (4.9999 + 0.1 ),则导致可以认为 5.0000 < 4.9999,这显然是荒唐的。

  • 相关阅读:
    ubuntu 16.04 连接无线网络
    linux的内存管理-抛砖引玉
    linux的进程调度-抛砖引玉
    AliOS Things 异步事件框架Yloop
    AliOS Things 云端物联网操作系统
    linux performance tools
    linux进程调度
    linux 内核Lockup机制浅析
    cache和内存屏障
    linux设备模型及实例
  • 原文地址:https://www.cnblogs.com/hoodlum1980/p/2535133.html
Copyright © 2011-2022 走看看