1 条题解

  • 0
    @ 2025-4-8 14:24:45

    题意

    给定坐标平面上的NN个边平行于坐标轴的正方形(所有顶点坐标为整数,且互不接触、不重叠),要求计算从原点O(0,0)O(0, 0)可见的正方形数量。 若某正方形的某条边上存在两个不同的点 A A 和 B B,使得三角形 OAB OAB 的内部与其余所有正方形均无公共点,则该正方形从原点可见。核心条件:输入:每个正方形由左下角坐标(X,Y)(X, Y) 和边长 L 确定,右上角坐标为 (X+L,Y+L)(X+L, Y+L)。存在一条边(上下左右四边之一)上的两个点 A A, BB,使得原点与这两个点形成的三角形内部完全不覆盖其他任何正方形。 目标:统计满足上述条件的正方形个数。

    解题思路

    判断左边和底边的覆盖,分别计算每个squaresquare的覆盖区域和长度。 解题报告里也是计算覆盖,不过用斜率代替了我分别计算的左边和底边,同时这里我原先用的是doubledouble,但是以斜。 率计算可以优化为记录斜率的点,这样就不需要用doubledouble,解决了精度问题。 然后是判断squaresquare的重叠问题,我原先是分成两部分的,左边和底边的在后的被在前的覆盖,报告里这里有更好的。 算法,记录边界点,以xx轴和yy轴坐标和来判断哪个被哪个覆盖。 最后只要对每一个squaresquare,从上到下找出被覆盖的斜率,然后最后被覆盖的位置相对于圆点的斜率大于squaresquare右下。 角点的相对于圆点的斜率,那么这个squaresquare必然没被覆盖完全,也就是看得到。

    标程

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    
    typedef struct
    {
        long x,y;
        long L;
    }point;
    
    point zero = {0, 0};
    point p[1005];
    
    int cross( point p0, point p1 , point p2)
    {
        int t = ( p1.x -p0.x ) * ( p2.y -p0.y ) -( p2.x -p0.x ) * ( p1.y -p0.y);
        if ( t > 0 )
            return 1;
        if ( t < 0 )
            return -1 ;
        return 0 ;
    }
    bool cmp(point a , point b )
    {
        return cross( zero , a, b ) < 0;//按斜率降序排列
    }
    int main()
    {
        long n , i , j , count;
        point tmp1 , tmp2;
        scanf("%ld", &n) ;
        for ( i = 0 ; i < n; i ++)
        {
            scanf("%ld %ld %ld" , &p[i].x, &p[i].y , &p[i].L);
            p[i].y += p[i].L;
        }
        sort(p, p + n, cmp);
        count = 0 ;
        for ( i = 0 ; i < n; i ++)
        {
            tmp1 = p[i] ;
            for ( j = 0 ; j < n; j ++)
            {
                if ( p[i].x + p[i].y <= p[j].x + p[j].y )
                    continue;
    
                tmp2.x = p[j].x + p[j].L ;
                tmp2.y = p[j].y -p[j].L;
                int t1 = cross(zero, p[j] , tmp1 ) ;
                 int t2 = cross(zero, tmp2, tmp1 ) ;
                if ( t1 != t2 )//不等的情况必然有覆盖
                    tmp1 = tmp2;
                else if(t1 > 0)
                    break;//由于按斜率降序排序,第j的点斜率都小于tmp1,那么后面的必然小于
            }
            tmp2.x = p[i].x + p[i].L ;
            tmp2.y = p[i].y - p[i].L ;
            if ( cross(zero, tmp2, tmp1 )> 0 )
                count ++;
        }
        printf("%ld\n", count) ;
    
        return 0;
    }
    
    • 1

    信息

    ID
    721
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    2
    已通过
    1
    上传者