POJ 2318 TOYS 判断点和线段的关系

TOYS
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 8889 Accepted: 4230

Description

Calculate the number of toys that land in each bin of a partitioned toy box. 
Mom and dad have a problem - their child John never puts his toys away when he is finished playing with them. They gave John a rectangular box to put his toys in, but John is rebellious and obeys his parents by simply throwing his toys into the box. All the toys get mixed up, and it is impossible for John to find his favorite toys. 

John's parents came up with the following idea. They put cardboard partitions into the box. Even if John keeps throwing his toys into the box, at least toys that get thrown into different bins stay separated. The following diagram shows a top view of an example toy box. 
 
For this problem, you are asked to determine how many toys fall into each partition as John throws them into the toy box.

Input

The input file contains one or more problems. The first line of a problem consists of six integers, n m x1 y1 x2 y2. The number of cardboard partitions is n (0 < n <= 5000) and the number of toys is m (0 < m <= 5000). The coordinates of the upper-left corner and the lower-right corner of the box are (x1,y1) and (x2,y2), respectively. The following n lines contain two integers per line, Ui Li, indicating that the ends of the i-th cardboard partition is at the coordinates (Ui,y1) and (Li,y2). You may assume that the cardboard partitions do not intersect each other and that they are specified in sorted order from left to right. The next m lines contain two integers per line, Xj Yj specifying where the j-th toy has landed in the box. The order of the toy locations is random. You may assume that no toy will land exactly on a cardboard partition or outside the boundary of the box. The input is terminated by a line consisting of a single 0.

Output

The output for each problem will be one line for each separate bin in the toy box. For each bin, print its bin number, followed by a colon and one space, followed by the number of toys thrown into that bin. Bins are numbered from 0 (the leftmost bin) to n (the rightmost bin). Separate the output of different problems by a single blank line.

Sample Input

5 6 0 10 60 0
3 1
4 3
6 8
10 10
15 30
1 5
2 1
2 8
5 5
40 10
7 9
4 10 0 10 100 0
20 20
40 40
60 60
80 80
 5 10
15 10
25 10
35 10
45 10
55 10
65 10
75 10
85 10
95 10
0

Sample Output

0: 2
1: 1
2: 1
3: 1
4: 0
5: 1

0: 2
1: 2
2: 2
3: 2
4: 2

Hint

As the example illustrates, toys that fall on the boundary of the box are "in" the box.

题目大意:

    有个小屁孩的父母给这个小屁孩搞了一个大箱子装玩具,这个箱子有n块纸板将大箱子分成了n+1个区间,小屁孩有m个玩具,输入第一行给出n,m,箱子的左上角坐标,箱子的右下角坐标。输出要你判断在第0~n个区间内分别有多少个玩具。

解题思路:

    我们把n块纸板和箱子的左右两边可以看成n+1个区间,区间编号为0~n,我们把箱子的左右当成第0块和第n+1块纸板。题目保证输入的玩具坐标不会超过箱子的上下限,所以我们只要判断左右即可。即判断第k个玩具在不在第i个区间内,就只要判断点P[k](xk,yk)是否在纸板i和纸板i+1中间就行了(当然正好在纸板上也算,不过这一题应该是按照从左到右的顺序)。把纸板 i 和箱底边的交点记为d[i],与上边的交点记为u[i],我们可以得到一个矢量v1=d[i]->u[i]。同样我们能够得到一个矢量v2=d[i]->p[k],如果v1 X v2 > 0 v2在v1的左边,=0则重合,<0则在右边,这样我们就可以进行判断了。

代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define maxn 5010
#define eps 10e-9

struct Point
{
    double x,y;
}toy[maxn],u[maxn+2],d[maxn+2],lu,rd;

int n,m,cnt[maxn+2];

double Cross ( Point A , Point B , Point C )
{
    double x1 = A.x - C.x;
    double x2 = B.x - C.x;
    double y1 = A.y - C.y;
    double y2 = B.y - C.y;

    return x1*y2 - x2 *y1;
}

int main()
{
    //freopen( "input.txt" , "r" , stdin) ;
    //freopen( "output.txt" , "w" , stdout );
    while ( ~scanf ( "%d" , &n ) && n )
    {
        memset ( cnt , 0 , sizeof ( cnt ) );
        scanf ( "%d %lf %lf %lf %lf" , &m , &lu.x , &lu.y , &rd.x , &rd.y );
        u[0].x = lu.x;
        u[0].y = lu.y;
        u[n+1].x = rd.x;
        u[n+1].y = lu.y;
        d[0].x = lu.x;
        d[0].y = rd.y;
        d[n+1].x = rd.x;
        d[n+1].y = rd.y;
        
        for ( int i = 1 ; i <= n ; i ++ )
        {
            scanf ( "%lf %lf" , &u[i].x , &d[i].x );
            u[i].y = lu.y;
            d[i].y = rd.y;
        }
        
        for ( int i = 0 ; i < m ; i ++ )
            scanf ( "%lf %lf" , &toy[i].x , &toy[i].y );
        for ( int i = 0 ; i < m ; i ++ )
        {
            for ( int j = 1 ; j <= n +1 ; j ++ )
            {
                double t1 = Cross ( toy[i] , d[j-1] , u[j-1] );
                double t2 = Cross ( toy[i] , d[j] , u[j] ); 
                if ( t1 * t2 < eps )
                {
                    cnt[j-1] ++;
                    break;
                }
            }
        }
        for ( int i = 0 ; i <= n ; i ++ )
        {
            printf ( "%d: %d\n" , i , cnt[i] );
        }
        printf ( "\n" );
    }
    return 0;
}

技巧总结:

    计算几何的基础点的位置问题,实际上也是线段的位置问题,熟练结构体,叉乘等重要性质和模板很重要。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值