POJ2318&&POJ2398

POJ2318
主要利用叉积的一点性质;对于每个点暴力遍历所有的边即可;
这里写图片描述

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include<iostream>
using namespace std;
const int MAXN = 5005;
const double EPS = 1e-8;

// 带误差比较
inline bool dcmp(double x, double y = 0)
{
    return fabs(x - y) <= EPS;
}

/*
 * 向量(Vector)或点
 *
 * 使用原点到一个点 (x, y) 的有向线段表示向量
 * 从点 A 到点 B 的向量表示为 A - B
 */
typedef struct Vec
{
    double x, y;

    Vec(double x = 0, double y = 0) : x(x), y(y) {}

    // 相加
    Vec operator+(const Vec &v) const
    {
        return Vec(x + v.x, y + v.y);
    }

    // 相减
    Vec operator-(const Vec &v) const
    {
        return Vec(x - v.x, y - v.y);
    }

    // 数乘(伸长、缩短)
    Vec operator*(double d) const
    {
        return Vec(x * d, y * d);
    }

    Vec operator/(const double d) const
    {
        return Vec(x / d, y / d);
    }

    // 范数,用来比较长度,等于长度的平方
    double norm() const
    {
        return x * x + y * y;
    }
} Pt;

// 点乘
double dot(const Vec &a, const Vec &b)
{
    return a.x * b.x + a.y * b.y;
}

// 叉乘
double cross(const Vec &a, const Vec &b)
{
    return a.x * b.y - a.y * b.x;
}

// 线段(Segment),用两个点表示
struct Seg
{
    Pt a, b;

    Seg(const Pt &a, const Pt &b) : a(a), b(b) {}

    // 线段包含点(点在线段上)
    bool include(const Pt &p)
    {
        // PA × PB = 0:PA 与 PB 共线,即点在线段所在的直线上
        // PA · PB = 0:PA 与 PB 方向不同(A 和 B 分别在 P 的两边),如果 PA · PB = 0 则 P = A 或 P = B
        return dcmp(cross(a - p, b - p)) && dot(a - p, b - p) <= 0;
    }
};

// 直线,用两个点表示
struct Line
{
    Pt a, b;

    Line() {} // 提供一个不需要参数的构造函数
    Line(const Pt &a, const Pt &b) : a(a), b(b) {}

    bool include(const Pt &p) const
    {
        return dcmp(cross(a - p, b - p));
    }

    // 两直线关系(交点个数)
    // 0 表示平行(无交点)
    // 1 表示相交(一个交点)
    // -1 表示重合(无数个交点)
    static int relation(const Line &a, const Line &b)
    {
        if (a.include(b.a) && a.include(b.b)) return -1;
         else if (dcmp(cross(a.b - a.a, b.b - b.a))) return 0;
        else return 1;
    }

    // 求两直线交点(需要保证两直线有交点)
    static Pt intersect(const Line &a, const Line &b)
    {
        double s1 = cross(b.a - a.a, b.b - a.a), s2 = cross(b.b - a.b, b.a - a.b);
        return a.a + (a.b - a.a) * s1 / (s1 + s2);
    }
};
int main()
{
    int n,m,x1,x2,y1,y2,i,j,k;
    while(cin>>n&&n){
        cin>>m;
        cin>>x1>>y1>>x2>>y2;
        Line p[MAXN];
        for(i=1;i<=n;i++){
            scanf("%lf%lf",&p[i].a.x,&p[i].b.x);p[i].a.y=y1;p[i].b.y=y2;
        }
        p[0].a.x=x1,p[0].a.y=y1,p[0].b.x=x1,p[0].b.y=y2;//把左右边界加进去当间隔
        p[n+1].a.x=x2,p[n+1].a.y=y1,p[n+1].b.x=x2,p[n+1].b.y=y2;
        int cnt[MAXN]={0};
        for(i=1;i<=m;i++){
            Pt t;scanf("%lf%lf",&t.x,&t.y);
            for(j=0;j<=n+1;j++){
                Vec t1,t2;t1=p[j].a-t;t2=p[j].b-t;//求点到每一个间隔的两个向量
                if(cross(t1,t2)<0)break;//如果连向下面点的向量在连向上面点的向量的顺时针方向,break;
            }
            cnt[j-1]++;
        }
        for(i=0;i<=n;i++)printf("%d: %d\n",i,cnt[i]);
        cout<<endl;
    }

    return 0;
}

POJ 2398
跟上一题基本上就一回事..只不过要注意这里加边的时候不一定是按从左到右的顺序的,所以加完以后要对边排个序;

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include<iostream>
#include<map>
using namespace std;
const int MAXN = 5005;
const double EPS = 1e-8;

// 带误差比较
inline bool dcmp(double x, double y = 0)
{
    return fabs(x - y) <= EPS;
}

/*
 * 向量(Vector)或点
 *
 * 使用原点到一个点 (x, y) 的有向线段表示向量
 * 从点 A 到点 B 的向量表示为 A - B
 */
typedef struct Vec
{
    double x, y;

    Vec(double x = 0, double y = 0) : x(x), y(y) {}

    // 相加
    Vec operator+(const Vec &v) const
    {
        return Vec(x + v.x, y + v.y);
    }

    // 相减
    Vec operator-(const Vec &v) const
    {
        return Vec(x - v.x, y - v.y);
    }

    // 数乘(伸长、缩短)
    Vec operator*(double d) const
    {
        return Vec(x * d, y * d);
    }

    Vec operator/(const double d) const
    {
        return Vec(x / d, y / d);
    }

    // 范数,用来比较长度,等于长度的平方
    double norm() const
    {
        return x * x + y * y;
    }
} Pt;

// 点乘
double dot(const Vec &a, const Vec &b)
{
    return a.x * b.x + a.y * b.y;
}

// 叉乘
double cross(const Vec &a, const Vec &b)
{
    return a.x * b.y - a.y * b.x;
}

// 线段(Segment),用两个点表示
struct Seg
{
    Pt a, b;

    Seg(const Pt &a, const Pt &b) : a(a), b(b) {}

    // 线段包含点(点在线段上)
    bool include(const Pt &p)
    {
        // PA × PB = 0:PA 与 PB 共线,即点在线段所在的直线上
        // PA · PB = 0:PA 与 PB 方向不同(A 和 B 分别在 P 的两边),如果 PA · PB = 0 则 P = A 或 P = B
        return dcmp(cross(a - p, b - p)) && dot(a - p, b - p) <= 0;
    }
};

// 直线,用两个点表示
struct Line
{
    Pt a, b;

    Line() {} // 提供一个不需要参数的构造函数
    Line(const Pt &a, const Pt &b) : a(a), b(b) {}

    bool include(const Pt &p) const
    {
        return dcmp(cross(a - p, b - p));
    }

    // 两直线关系(交点个数)
    // 0 表示平行(无交点)
    // 1 表示相交(一个交点)
    // -1 表示重合(无数个交点)
    static int relation(const Line &a, const Line &b)
    {
        if (a.include(b.a) && a.include(b.b)) return -1;
        else if (dcmp(cross(a.b - a.a, b.b - b.a))) return 0;
        else return 1;
    }

    // 求两直线交点(需要保证两直线有交点)
    static Pt intersect(const Line &a, const Line &b)
    {
        double s1 = cross(b.a - a.a, b.b - a.a), s2 = cross(b.b - a.b, b.a - a.b);
        return a.a + (a.b - a.a) * s1 / (s1 + s2);
    }
};
bool cmp(Line a,Line b)
{
    return a.a.x<b.a.x;
}
int main()
{
    int n,m,x1,x2,y1,y2,i,j,k;
    while(cin>>n&&n){
        cin>>m;
        cin>>x1>>y1>>x2>>y2;
        Line p[MAXN];
        for(i=1;i<=n;i++){
            scanf("%lf%lf",&p[i].a.x,&p[i].b.x);p[i].a.y=y1;p[i].b.y=y2;
        }
        p[0].a.x=x1,p[0].a.y=y1,p[0].b.x=x1,p[0].b.y=y2;//把左右边界加进去当间隔
        p[n+1].a.x=x2,p[n+1].a.y=y1,p[n+1].b.x=x2,p[n+1].b.y=y2;sort(p,p+n+1,cmp);
        int cnt[MAXN]={0};
        for(i=1;i<=m;i++){
            Pt t;scanf("%lf%lf",&t.x,&t.y);
            for(j=0;j<=n+1;j++){
                Vec t1,t2;t1=p[j].a-t;t2=p[j].b-t;//求点到每一个间隔的两个向量
                if(cross(t1,t2)<0)break;//如果连向下面点的向量在连向上面点的向量的顺时针方向,break;
            }
            cnt[j-1]++;
        }
        map<int,int>m1;
        for(i=0;i<=n;i++){
            //cout<<cnt[i]<<endl;
            if(cnt[i])
                m1[cnt[i]]++;
        }
        printf("Box\n");
        map<int,int>::iterator iter;
        for(iter=m1.begin();iter!=m1.end();iter++)
            printf("%d: %d\n",iter->first,iter->second);
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/humveea6/article/details/80272815
今日推荐