ACM/ICPC 之 计算几何入门-叉积-to left test(POJ2318-POJ2398)

  POJ2318

  本题需要运用to left test不断判断点处于哪个分区,并统计分区的点个数(保证点不在边界和界外),用来做叉积入门题很合适

 

//计算几何-叉积入门题
//Time:157Ms    Memory:828K
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 5005
struct Point{
    int x,y;
    Point(int xx=0, int yy=0):x(xx), y(yy){}
    friend bool operator < (Point p1, Point p2){
        return (p1.x < p2.x) || (p1.x == p2.x && p1.y < p2.y);
    }
}ul, lr, p[2*MAXN], toy[MAXN];
int n, m;
int num[MAXN];
int cross(Point a, Point b, Point s)//叉积-(s在ab左侧返回>0)
{
    return (a.x-s.x) * (b.y-s.y) - (a.y-s.y) * (b.x-s.x);
}
int main()
{
    //freopen("in.txt", "r", stdin);
    while(scanf("%d", &n), n)
    {
        memset(num, 0, sizeof(num));
        scanf("%d%d%d%d%d", &m, &ul.x, &ul.y, &lr.x, &lr.y);
        for(int i=0; i<n; i++)
        {
            int u,l;
            scanf("%d%d", &u,&l);
            p[2*i] = Point(u, ul.y);
            p[2*i+1] = Point(l, lr.y);
        }
        p[2*n] = Point(lr.x, ul.y);
        p[2*n+1] = Point(lr.x, lr.y);
        for(int i=0; i<m; i++)
            scanf("%d%d", &toy[i].x, &toy[i].y);
        sort(toy, toy+m);
        int cur = 0;
        for(int i=0; i<m; i++)
        {
            for(int j=cur; j<=n; j++)
            {
                if(cross(p[j*2+1], p[j*2], toy[i]) > 0) //to left test
                {
                    num[j]++;   break;
                }
            }
            while(toy[i].x > max(p[cur*2+1].x, p[cur*2].x))
                cur++;
        }
        for(int i = 0; i <= n;i++)
            printf("%d: %d\n", i, num[i]);
        printf("\n");
    }
    return 0;
}

 

 

  POJ2398

  题意同上,不同在于线段是随机的(需对线段排序),且要求输出为相同统计数的格子数量

  

//计算几何-叉积入门题-需对线段排序
//题意同POJ2318
//Time:0Ms    Memory:724K
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 1005
struct Point{
    int x,y;
    Point(int xx=0, int yy=0):x(xx), y(yy){}
    friend bool operator < (Point p1, Point p2){
        return (p1.x < p2.x) || (p1.x == p2.x && p1.y < p2.y);
    }
}ul, lr, toy[MAXN];
struct Line{
    int a,b,c,d;
    Line(int aa=0, int bb=0, int cc=0, int dd=0):a(aa),b(bb),c(cc),d(dd){}
    friend bool operator < (Line l1, Line l2){
        return (l1.a < l2.a) || (l1.a == l2.a && l1.c < l2.c);
    }
}line[MAXN];
int n, m;
int num[MAXN], cnt[MAXN];
int cross(Point a, Point b, Point s)//叉积-(s在ab左侧返回>0)
{
    return (a.x-s.x) * (b.y-s.y) - (a.y-s.y) * (b.x-s.x);
}
int main()
{
    //freopen("in.txt", "r", stdin);
    while(scanf("%d", &n), n)
    {
        memset(num, 0, sizeof(num));
        memset(cnt, 0, sizeof(cnt));
        scanf("%d%d%d%d%d", &m, &ul.x, &ul.y, &lr.x, &lr.y);
        for(int i=0; i<n; i++)
        {
            int u,l;
            scanf("%d%d", &u,&l);
            line[i] = Line(u, ul.y, l, lr.y);
        }
        line[n] = Line(lr.x, ul.y, lr.x, lr.y);
        sort(line, line+n+1);
        for(int i=0; i<m; i++)
            scanf("%d%d", &toy[i].x, &toy[i].y);
        sort(toy, toy+m);
        int cur = 0;
        for(int i=0; i<m; i++)
        {
            for(int j=cur; j<=n; j++)
            {
                if(cross(Point(line[j].c, line[j].d), Point(line[j].a,line[j].b), toy[i]) > 0) //to left test
                {
                    num[j]++;   break;
                }
            }
            while(toy[i].x > max(line[cur].a, line[cur].c))
                cur++;
        }
        for(int i=0; i<=n; i++)
            cnt[num[i]]++;
        printf("Box\n");
        for(int i = 1; i <= n;i++)
            if(cnt[i]) printf("%d: %d\n", i, cnt[i]);
    }
    return 0;
}

 

    原文作者:Inkblots
    原文地址: https://www.cnblogs.com/Inkblots/p/5728494.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞