1 条题解
-
0
题意
给定坐标平面上的个边平行于坐标轴的正方形(所有顶点坐标为整数,且互不接触、不重叠),要求计算从原点可见的正方形数量。 若某正方形的某条边上存在两个不同的点 和,使得三角形 的内部与其余所有正方形均无公共点,则该正方形从原点可见。核心条件:输入:每个正方形由左下角坐标 和边长 确定,右上角坐标为 。存在一条边(上下左右四边之一)上的两个点, ,使得原点与这两个点形成的三角形内部完全不覆盖其他任何正方形。 目标:统计满足上述条件的正方形个数。
解题思路
判断左边和底边的覆盖,分别计算每个的覆盖区域和长度。 解题报告里也是计算覆盖,不过用斜率代替了我分别计算的左边和底边,同时这里我原先用的是,但是以斜。 率计算可以优化为记录斜率的点,这样就不需要用,解决了精度问题。 然后是判断的重叠问题,我原先是分成两部分的,左边和底边的在后的被在前的覆盖,报告里这里有更好的。 算法,记录边界点,以轴和轴坐标和来判断哪个被哪个覆盖。 最后只要对每一个,从上到下找出被覆盖的斜率,然后最后被覆盖的位置相对于圆点的斜率大于右下。 角点的相对于圆点的斜率,那么这个必然没被覆盖完全,也就是看得到。
标程
#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
- 上传者