zoukankan      html  css  js  c++  java
  • HDU 1221 Rectangle and Circle 考虑很多情况,good题

    http://acm.hdu.edu.cn/showproblem.php?pid=1221

    1
    14 92 31 95 13 96 3

    这题只需要判断圆和矩形是否相交,然后在里面是不算相交的。

    那么就有好几种情况了。

    1、整个矩形在圆形里,NO,(我的做法是所有点到圆心距离小于半径)

    2、整个圆在矩形里,NO,一个圆选出5个点,圆心,和最上下左右,如果这些点都在,则不行。我的做法直接PointInPolygon。

    3、否则,只要有公共点,就直接YES。然后,如果圆那5个点有一个在矩形,或者矩形的4个点到圆心的距离小于半径,即可。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #define IOS ios::sync_with_stdio(false)
    #define MY "H:/CodeBlocks/project/CompareTwoFile/DataMy.txt", "w", stdout
    #define ANS "H:/CodeBlocks/project/CompareTwoFile/DataAns.txt", "w", stdout
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    
    #include <iostream>
    #include <sstream>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    const double eps = 1e-15;
    bool same(double x, double y) {
        return fabs(x - y) < eps;
    }
    struct coor {
        double x,y;
        coor() {}
        coor(double xx,double yy):x(xx),y(yy) {}
        double operator ^(coor rhs) const { //计算叉积(向量积),返回数值即可
            return x*rhs.y - y*rhs.x;
        }
        coor operator -(coor rhs) const { //坐标相减,a-b得到向量ba,返回一个向量(坐标形式)
            return coor(x-rhs.x,y-rhs.y);
        }
        double operator *(coor rhs) const { //数量积,返回数值即可
            return x*rhs.x + y*rhs.y;
        }
        bool operator ==(coor rhs) const {
            return same(x,rhs.x)&&same(y,rhs.y); //same的定义其实就是和eps比较
        }
    } a[111], cir[111];
    double dis(coor a, coor b) {
        return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
    }
    
    bool OnSegment (coor a,coor b,coor cmp) { //判断点cmp是否在线段ab上
        double min_x = min(a.x,b.x), min_y = min(a.y,b.y);
        double max_x = max(a.x,b.x), max_y = max(a.y,b.y);
        if (cmp.x>=min_x && cmp.x<=max_x && cmp.y>=min_y && cmp.y<=max_y) return true;
        else return false;
    }
    
    int PointInPolygon (coor p[],int n,coor cmp) {
        int cnt = 0; //记录单侧有多少个交点,这里的p[],必须有顺序
        for (int i=1; i<=n; ++i) {
            int t = (i+1)>n ? 1:(i+1);  //下标为1要这样MOD
            coor p1=p[i],p2=p[t];
            //printf ("%lf %lf %lf %lf***
    ",p1.x,p1.y,p2.x,p2.y);
            if (OnSegment(p1,p2,cmp)) {
                coor t1 = p1-cmp,t2 = p2-cmp; //同时要叉积等于0,这是在线段上的前提
                if ((t1^t2)==0) return 2;// 2表明在多边形上,可以适当省略
            }
            if (cmp.y >= max(p1.y,p2.y)) continue;//交点在延长线上和在凸顶点上的都不要
            if (cmp.y <  min(p1.y,p2.y)) continue;//交点在凹顶点上就要,这里没取等
            if (same(p1.y,p2.y)) continue; //与cmp.y是平行的
            double x = (cmp.y-p1.y)*(p1.x-p2.x)/(p1.y-p2.y) + p1.x; //求交点 p1.y != p2.y不会除0
            if (x>cmp.x) cnt++;//只统计一侧的交点
        }
        return cnt&1;//0表明点在多边形外,1表明点在多边形内
    }
    
    void work() {
        double x, y, R;
        scanf("%lf%lf%lf", &x, &y, &R);
        double xx1, xx2, yy1, yy2;
        scanf("%lf%lf%lf%lf", &xx1, &yy1, &xx2, &yy2);
        int lena = 0;
        a[++lena] = coor(xx1, yy1);
        a[++lena] = coor(xx1, yy2);
        a[++lena] = coor(xx2, yy2);
        a[++lena] = coor(xx2, yy1);
    
        int lencir = 0;
        cir[++lencir] = coor(x + R, y);
        cir[++lencir] = coor(x, y + R);
        cir[++lencir] = coor(x - R, y);
        cir[++lencir] = coor(x, y - R);
        cir[++lencir] = coor(x, y);
        int up = 0;
        for (int i = 1; i <= lencir; ++i) {
            if (PointInPolygon(a, 4, cir[i])) {
                up++;
            }
            if (PointInPolygon(a, 4, cir[i]) == 2 && i != lencir) {
                printf("YES
    ");
                return;
            }
        }
        if (up == lencir) {
            printf("NO
    ");
            return;
        }
        up = 0;
        for (int i = 1; i <= lena; ++i) {
            double tdis = dis(a[i], coor(x, y));
            if (same(tdis, R)) {
                printf("YES
    ");
                return;
            }
            if (tdis < R) up++;
        }
        if (up == lena) {
            printf("NO
    ");
            return;
        }
        
        for (int i = 1; i <= lena; ++i) {
            double tdis = dis(a[i], coor(x, y));
            if (same(tdis, R) || tdis < R) {
                printf("YES
    ");
                return;
            }
        }
    
        for (int i = 1; i <= lencir; ++i) {
            if (PointInPolygon(a, 4, cir[i])) {
                printf("YES
    ");
                return;
            }
        }
        printf("NO
    ");
    //    cout << dis(coor(5,5), coor(7, 7)) << endl;
        return;
    }
    int main() {
    #ifdef local
        freopen("data.txt","r",stdin);
        freopen(MY);
    #endif
        int t;
        scanf("%d", &t);
        while (t--) {
            work();
        }
        return 0;
    }
    View Code

    开始的时候,判断有一个点在就行的时候,(就是相切的时候),把圆心也算进去了,坑了半天。

    https://www.desmos.com/calculator  分享个画图工具,矩形的话,就直接是x>=10 x <= 99这样画

  • 相关阅读:
    C#=>递归反转栈
    C#=> 栈模仿堆的操作
    C# 栈=>随时读取栈中最小值
    vijos1574 摇钱树
    (二叉)堆
    分块大法好
    list
    动态规划——状压、树形
    区间动规平行四边形优化
    最长公共子序列(LCS)
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/6082515.html
Copyright © 2011-2022 走看看