TopBoy

POJ 2318 TOYS

栏目:解题报告      1,021 Views      5 枚回复

http://acm.pku.edu.cn/JudgeOnline/problem?id=2318

题意:
     有一矩形,N条直线(直线不相交)把矩形分成N+1个区间,然后给定M个点,求矩形每个区间内有多少个点,如下图

算法:
     简单题,只要对每个点求出所在的区间然后计数,求区间时使用二分找到这个点右边或者左边的第一条直线即可,复杂度M*logN

代码:

#include<iostream>

using namespace std;

 

#define MAX 5005

int n, m;

double x1, y1, x2, y2;

double u[MAX], l[MAX];

double k[MAX];    // 斜率

double h;

int count[MAX];

 

void bsearch(double x, double y)

{

      int ma = n, mi = 0, mid;

      double rx;

      double ydis = y – y1;

      while(ma > mi)

      {

            mid = (ma+mi)>>1;

            rx = k[mid] * ydis + u[mid];

            if(rx<x)mi = mid+1;

            else if(rx>x)ma = mid;

      }

      count[ma]++;

}

int main()

{

      int i;

      double x, y;

      while(scanf(“%d”,&n)==1 && n)

      {

            memset(count, 0, sizeof(count));

            scanf(“%d %lf %lf %lf %lf”,&m,&x1,&y1,&x2,&y2);

            h = y2 – y1;

            for(i=0;i<n;++i)

            {

                  scanf(“%lf%lf”,&u[i], &l[i]);

                  k[i] = (l[i]-u[i])/h;

            }

            u[n] = x2; l[n] = x2; k[n] = 0;

            for(i=0;i<m;++i)

            {

                  scanf(“%lf%lf”,&x,&y);

                  bsearch(x, y);

            }

            for(i=0;i<=n;++i)

                  printf(“%d: %d\n”,i,count[i]);

            printf(“\n”);

      }

      return 0;

}

 


468 X 60 广告位

标签: , , ,

转载注明:转自TopBoy

本站遵循:署名-非商业性使用-禁止演绎 3.0 共享协议

收藏分享: QQ书签 / 百度收藏 / Google书签 / 收藏到鲜果 / Digg / Del.icio.us


5 枚回复


  1. David 说:

    N条直线(直线不相交) 是说平行线么?如果是,为什么每条直线都有一个斜率?如果不是,只是不在矩形内相交,你的二分查找有问题。

  2. TopBoy 说:

    @David
    请您先看一下题目http://acm.pku.edu.cn/JudgeOnline/problem?id=2318
    确切讲是被矩形切的线段是两两不相交的。
    二分没有问题的。
    你是不是觉得else if(rx>x)ma = mid;这句是错的?这句必须要这样写的,您认为呢?

  3. David 说:

    看了原题,你的方法好像应该没问题。

    我原来考虑的是,如果有隔板不是顶天立地的,如果出现隔板延长线的交点在 y1-y2 之间的,那取横线的交点就会出现乱序,这时候二分法会出错。

    比如说如下的情况:

    +————-
    | / /
    |/ /
    | /
    |/
    |
    |
    +————–

  4. TopBoy 说:

    @David
    对,你考虑的更多一些,题目比较简单

  5. 说:

    为什么我的程序老WA啊
    麻烦高手看一下:
    #include
    using namespace std;
    int N,M;
    int up_left_x,up_left_y,low_right_x,low_right_y;

    struct point
    {
    int a,b;
    }line[5005],toys[5005];
    int number[5005];

    void solve(int point, int left, int right)
    {
    int middle;
    int x1,y1,x2,y2;
    if(left+1==right)
    {number[left]++;return;}
    middle=(left+right)/2;
    x1=line[middle].a-line[middle].b; y1=up_left_y-low_right_y;
    x2=toys[point].a-line[middle].b; y2=toys[point].b-low_right_y;
    if((x1*y2-x2*y1)>0)
    solve(point,left,middle);
    else
    solve(point,middle,right);

    }

    int main()
    {
    int i;
    int x1,y1,x2,y2,x3,y3;
    while(scanf(“%d”,&N),N)
    {
    scanf(“%d”,&M);
    scanf(“%d%d%d%d”,&up_left_x,&up_left_y,&low_right_x,&low_right_y);
    for(i=1;i<=N;i++)
    scanf("%d%d",&line[i].a,&line[i].b);
    for(i=1;i<=M;i++)
    scanf("%d%d",&toys[i].a,&toys[i].b);
    memset(number,0,sizeof(number));
    x1=line[1].a-line[1].b;y1=up_left_y-low_right_y;
    x2=line[N].a-line[N].b;y2=up_left_y-low_right_y;
    for(i=1;i0)
    {number[0]++;continue;}
    x3=toys[i].a-line[N].b; y3=toys[i].b-low_right_y;
    if((x1*y3-y1*x3)<0)
    {number[N]++;continue;}
    solve(i,1,N);
    }
    for(i=0;i<=N;i++)
    printf("%d: %d\n",i,number[i]);
    printf("\n");
    }
    return 0;
    }


发表回复


XHTML: 您可以使用如下代码:<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>