POJ2318 (二分+叉积)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yuewenyao/article/details/84074518

题目链接

题目大意:给你一个矩形和一些线段,给的这些线段将矩形分割为从左到右的若干个部分(不会相交,点不会再线上,题意给出了),之后给出一些玩具的坐标,求分割的若干部分每个部分的玩具数量。

题解:这是一个计算几何的水题,考一些基础问题,我们注意,题目上给线段的顺序是从左到右给出的,我们可以考虑的是每一个点(玩具)是在这条线的左边还是右边,(一定会存在一个分界使它的左边的线段都在玩具的右边,它右边的玩具都在玩具的左边)

于是我们能想出来这种情况下我们要用二分来写:

然后我们根据叉积判断点和线段的关系(我们可以将点减去线段的起点和原线段组成两个同七点的向量,然后我们根据叉积的性质:

若P×Q > 0 , 则P在Q的顺时针方向;

若P×Q < 0 , 则P在Q的逆时针方向;

若P×Q = 0 , P与Q共线,可能是同向也可能是反向

因为题目上说了,玩具保证不会落在分界线上,所以不用考虑)

扫描二维码关注公众号,回复: 4924837 查看本文章

特别注意:本题的数组有点儿多吧,注意初始化每一个数组。

AC代码如下:

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;

const int mx = 666666;

int u[mx] , v[mx] , ans[mx];

int chachen(int x1 , int y1 , int x2 , int y2)
{
    return x1 * y2 - x2 * y1;
}

int main()
{
    int n , m , x1 , y1 , x2 , y2 , flag = 0 ;
    while(scanf("%d%d%d%d%d%d",&n,&m,&x1,&y1,&x2,&y2) == 6)
    {
        if(flag)
            puts("");
        flag = 1;
        memset(ans,0,sizeof(ans));
        for(int i = 0 ; i < n ; i ++)
        {
            scanf("%d %d",&u[i],&v[i]);
        }
        int x , y ;
        for(int i = 1 ; i <= m ; i ++)
        {
            cin>>x>>y;
            int high = n , mid , low = 0 ;
            while(low < high)
            {
                mid = (low + high) / 2 ;
                if(chachen(u[mid] - x , y1 - y , v[mid] - x , y2 - y) <= 0)
                    high = mid;
                else
                    low = mid + 1 ;

            }
            ans[low]++;
        }
        for(int i = 0 ; i <= n ; i ++)
        {
            printf("%d: %d\n",i,ans[i]);
        }
    }
    return 0 ;
}

有的可能就是sort扫一遍然后输出就能过,可能使后台数据太水吧,那个我看要900多Ms,但是用二分的话差不多500Ms运行完

猜你喜欢

转载自blog.csdn.net/yuewenyao/article/details/84074518