zoukankan      html  css  js  c++  java
  • POJ 2308 TOYS

    题意:在一个长方形区域用n条直线分隔成n+1个部分,给定m个点,求这个区域的m个点,求点所在的部分。

    算法:二分搜索,点和直线的位置关系

    1,设直线的方程ax+bx+c=0(a>0);若点(x0,y0)代入方程:

      若ax0+by0+c<0,则点在直线的左侧;

      若ax0+by0+c=0,则点在直线上;

      若ax0+by0+c<0,则点在直线的右侧;

      但是前提是a>0,否则结果左右对调(WA了一次).

    2,(x1,y1)和(x2,y2)为某直线的两个点,直线的方程就可以表示为(y2-y1)(x-x1)-(x2-x1)(y-y1)=0;

      因为n较大,而直线与直线对点具有序的关系,即点如果在某条直线的左侧,那么肯定在那条直线右侧所有的直线的左侧,

    所以可用二分搜索把时间复杂度降为O(nlogn);

    #include<cstdio>
    #include<cstring>
    #define MAXN 5010
    using namespace std;
    
    int x,y,dy,n,x1,x2,y1,y2,dx[MAXN],Ui[MAXN];
    
    int BSearch()
    {
        int lt,rt,mid;
        for(lt=-1,rt=n;lt+1<rt;)
        {
            mid=(lt+rt)>>1;
            if(dy*(x-Ui[mid])-dx[mid]*(y-y1)<0)//因为y1>y2,所以dy>0
                rt=mid;
            else
                lt=mid;
        }
        return rt;
    }
    
    int main()
    {
        int m,i,Li,b[MAXN];
        for(;scanf("%d",&n),n;)
        {
            memset(b,0,sizeof(b));
            scanf("%d%d%d%d%d",&m,&x1,&y1,&x2,&y2);
            dy=y1-y2;
            for(i=0;i<n;i++)
            {
                scanf("%d%d",Ui+i,&Li);
                dx[i]=Ui[i]-Li;
            }
            for(;m--;)
            {
                scanf("%d%d",&x,&y);
                b[BSearch()]++;
            }
            for(i=0;i<=n;i++)
                printf("%d: %d\n",i,b[i]);
            puts("");
        }
        return 0;
    }
  • 相关阅读:
    LeetCode
    LeetCode
    LeetCode
    LeetCode
    thinkphp使用foreach遍历的方法
    php中foreach中使用&的办法
    thinkphp做搜索功能
    数据库虚拟主机目录的配置文件
    网页响应式设计原理
    数据库常见远程连接问题
  • 原文地址:https://www.cnblogs.com/xchaos/p/2465060.html
Copyright © 2011-2022 走看看