Kuangbin 带你飞-基础计算几何专题 题解

专题基本全都是模版应用。贴一下模版

const double eps = 1e-8;
const int INF = 0x3f3f3f3f;
int sgn(double x)
{
    if (fabs(x) < eps) return 0;
    if (x < 0) return -1;
    return 1;
}

struct Point
{
    double x,y;
    Point(){}
    Point(double tx,double ty)
    {
        x = tx;
        y = ty;
    }

    Point operator - (const Point &b) const
    {
        return Point(x - b.x,y - b.y);
    }
    //叉积
    double operator ^ (const Point &b) const
    {
        return x * b.y - y * b.x;
    }
    //点积
    double operator * (const Point &b) const
    {
        return x * b.x + y * b.y;
    }
    //绕源点旋转B(弧度)。后X,Y变化
    void transxy(double B) //
    {
        double tx = x;
        double ty = y;
        x = tx * cos(B) - ty * sin(B);
        y = ty * sin(B) + tx * cos(B);
    }
};

struct Line
{
    Point s,e;
    Line(){}
    Line(Point a,Point b)
    {
        s = a;
        e = b;
    }
    //两直线求交点。这个可以用来求线段交点。
   // 首先判断线段相交然后可以直接利用这个判线段交点
   //first为0表示重合,1表示平行,2表示相交
    pair<int,Point> operator & (const Line &b) const
    {
        Point res = s;
        if (sgn((s - e) ^ (b.s - b.e)) == 0)
        {
            if (sgn((s - b.e) ^ (b.s - b.e)) == 0)
                return make_pair(0,res);//重合
            else return make_pair(1,res);//平行
        }
        double t = ((s - b.s) ^ (b.s - b.e)) / ((s - e) ^ (b.s - b.e));//相交
        res.x += (e.x - s.x) * t;
        res.y += (e.y - s.y) * t;
        return make_pair(2,res);
    }
};

double dist(Point a,Point b)
{
    return sqrt((b - a) * (b - a));
}
//判断线段是否相交
bool inter(Line l1,Line l2)
{
     return max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x) &&
        max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x) &&
        max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y) &&
        max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y) &&
        sgn((l2.s - l1.s) ^ (l1.e - l1.s)) * sgn((l2.e - l1.s) ^ (l1.e - l1.s)) <= 0 &&
        sgn((l1.s - l2.s) ^ (l2.e - l1.s)) * sgn((l1.e - l2.s) ^ (l2.e - l2.s)) <= 0;
}
bool OnSeg(Point P,Line L)
{
    return
    sgn((L.s-P)^(L.e-P)) == 0 &&
    sgn((P.x - L.s.x) * (P.x - L.e.x)) <= 0 &&
    sgn((P.y - L.s.y) * (P.y - L.e.y)) <= 0;
}

//判断点在凸多边形内
//点形成一个凸包,而且按逆时针排序(如果是顺时针把里面的<0改为>0)一定注意时针顺序否则会WA
//点的编号:0~n-1
//返回值:
//-1:点在凸多边形外
//0:点在凸多边形边界上
//1:点在凸多边形内
int inConvexPoly(Point a,Point p[],int n)
{
    for(int i = 0 ; i < n ; i++)
    {
        if(sgn((p[i] - a) ^ (p[(i + 1) % n] - a)) < 0)return -1;
        else if(OnSeg(a,Line(p[i],p[(i + 1) % n])))return 0;
    }
    return 1;
}

//判断点在任意多边形内
//射线法,poly[]的顶点数要大于等于3,点的编号0~n-1
//返回值
//-1:点在凸多边形外
//0:点在凸多边形边界上
//1:点在凸多边形内
int inPoly(Point p,Point poly[],int n)
{
    int cnt;
    Line ray,side;
    cnt = 0;
    ray.s = p;
    ray.e.y = p.y;
    ray.e.x = -100000000000.0;//-INF,注意取值防止越界

    for(int i = 0;i < n;i++)
    {
        side.s = poly[i];
        side.e = poly[(i+1)%n];

        if(OnSeg(p,side))return 0;

        //如果平行轴则不考虑
        if(sgn(side.s.y - side.e.y) == 0)
            continue;

        if(OnSeg(side.s,ray))
        {
            if(sgn(side.s.y - side.e.y) > 0)cnt++;
        }
        else if(OnSeg(side.e,ray))
        {
            if(sgn(side.e.y - side.s.y) > 0)cnt++;
        }
        else if(inter(ray,side))
            cnt++;
    }
    if(cnt % 2 == 1)return 1;
    else return -1;
}
//判断凸多边形
//允许共线边
//点可以是顺时针给出也可以是逆时针给出
//点的编号1~n-1
bool isconvex(Point poly[],int n)
{
    bool s[3];
    memset(s,false,sizeof(s));
    for(int i = 0;i < n;i++)
    {
        s[sgn( (poly[(i + 1) % n]-poly[i]) ^ (poly[(i + 2) % n] - poly[i]) ) + 1] = true;
        if(s[0] && s[2])return false;
    }
    return true;
}

//点到线段的距离
//返回点到线段最近的点
Point NearestPointToLineSeg(Point P,Line L)
{
    Point result;
    double t = ((P - L.s)*(L.e - L.s)) / ((L.e - L.s)*(L.e - L.s));
    if(t >= 0 && t <= 1)
    {
        result.x = L.s.x + (L.e.x - L.s.x) * t;
        result.y = L.s.y + (L.e.y - L.s.y) * t;
    }
    else
    {
        if(dist(P,L.s) < dist(P,L.e))
            result = L.s;
        else result = L.e;
    }
    return result;
}

//*判断点在线段上
bool OnSeg(Point P,Line L)
{
    return
    sgn((L.s-P)^(L.e-P)) == 0 &&
    sgn((P.x - L.s.x) * (P.x - L.e.x)) <= 0 &&
    sgn((P.y - L.s.y) * (P.y - L.e.y)) <= 0;
}

//*判断点在凸多边形内
//点形成一个凸包,而且按逆时针排序(如果是顺时针把里面的<0改为>0)
//点的编号:0~n-1
//返回值:
//-1:点在凸多边形外
//0:点在凸多边形边界上
//1:点在凸多边形内
int inConvexPoly(Point a,Point p[],int n)
{
    for(int i = 0 ; i < n ; i++)
    {
        if(sgn((p[i] - a) ^ (p[(i + 1) % n] - a)) < 0)return -1;
        else if(OnSeg(a,Line(p[i],p[(i + 1) % n])))return 0;
    }
    return 1;
}

bool inter(Line l1,Line l2)
{
    return
    max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x) &&
    max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x) &&
    max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y) &&
    max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y) &&
    sgn((l2.s - l1.e) ^ (l1.s - l1.e)) * sgn((l2.e - l1.e) ^ (l1.s - l1.e)) <= 0 &&
    sgn((l1.s - l2.e) ^ (l2.s - l2.e)) * sgn((l1.e - l2.e) ^ (l2.s - l2.e)) <= 0;
}

    //*判断点在任意多边形内
//射线法,poly[]的顶点数要大于等于3,点的编号0~n-1
//返回值
//-1:点在凸多边形外
//0:点在凸多边形边界上
//1:点在凸多边形内
int inPoly(Point p,Point poly[],int n)
{
    int cnt;
    Line ray,side;
    cnt = 0;
    ray.s = p;
    ray.e.y = p.y;
    ray.e.x = -100000000000.0;//-INF,注意取值防止越界

    for(int i = 0;i < n;i++)
    {
        side.s = poly[i];
        side.e = poly[(i+1)%n];

        if(OnSeg(p,side))return 0;

        //如果平行轴则不考虑
        if(sgn(side.s.y - side.e.y) == 0)
            continue;

        if(OnSeg(side.s,ray))
        {
            if(sgn(side.s.y - side.e.y) > 0)cnt++;
        }
        else if(OnSeg(side.e,ray))
        {
            if(sgn(side.e.y - side.s.y) > 0)cnt++;
        }
        else if(inter(ray,side))
            cnt++;
    }
    if(cnt % 2 == 1)return 1;
    else return -1;
}

POJ 2318 TOYS

给出区域,要你算出给出的每个点在第几个区域里

利用叉积的方向性二分判断在第几个区域内

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
typedef long long type;
using namespace std;
type gcd(type a, type b) {return b == 0 ? a : gcd(b, a % b);}
const int MAXN = 5030;

struct Point
{
    int x,y;
    Point(){}
    Point(int _x,int _y)
    {
        x = _x;y = _y;
    }
    Point operator - (const Point &b)const
    {
        return Point(x - b.x,y - b.y);
    }
    int operator * (const Point &b)const
    {
        return x*b.x + y*b.y;
    }
    int operator ^ (const Point &b)const
    {
        return x*b.y - y*b.x;
    }
};

struct Line
{
    Point s,e;
    Line(){}
    Line(Point _s,Point _e)
    {
        s = _s;e = _e;
    }
};

int xmult(Point p0,Point p1,Point p2) //计算p0p1 X p0p2
{
    return (p1 - p0) ^ (p2 - p0);
}

Line line[MAXN];
int ret[MAXN];
int N,M;
double X1,Y1,X2,Y2;

int main()
{
    bool first = true;
    while (scanf("%d",&N) != EOF)
    {
        if(N == 0) break;
        if (first) first = false;
        else putchar(‘\n‘);
        memset(ret,0,sizeof(ret));
        scanf("%d%lf%lf%lf%lf",&M,&X1,&Y1,&X2,&Y2);
        int UI,LI;
        for (int i = 0 ; i < N ; i++)
        {
            scanf("%d%d",&UI,&LI);
            line[i] = Line(Point(UI,Y1),Point(LI,Y2));
        }
        line[N] = Line(Point(X2,Y1),Point(X2,Y2));
        Point p;
        memset(ret,0,sizeof(ret));
        while (M--)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            p = Point(x,y);
            int l = 0,r = N;
            int ans;
            while (l <= r)
            {
                int mid = (l + r) / 2;
                if (xmult(p,line[mid].s,line[mid].e) < 0)
                {
                    ans = mid;
                    r = mid - 1;
                }
                else l = mid + 1;
            }
            ret[ans]++;
        }
        for (int i = 0 ; i <= N ; i++) printf("%d: %d\n",i,ret[i]);
    }
    return 0;
}

POJ 2398 Toy Storage

跟上面的那个题一样的只是改变了一下答案的方式

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
typedef long long type;
using namespace std;
type gcd(type a, type b) {return b == 0 ? a : gcd(b, a % b);}
const int MAXN = 5030;

struct Point
{
    int x,y;
    Point(){}
    Point(int _x,int _y)
    {
        x = _x;y = _y;
    }
    Point operator - (const Point &b)const
    {
        return Point(x - b.x,y - b.y);
    }
    int operator * (const Point &b)const
    {
        return x*b.x + y*b.y;
    }
    int operator ^ (const Point &b)const
    {
        return x*b.y - y*b.x;
    }
};

struct Line
{
    Point s,e;
    Line(){}
    Line(Point _s,Point _e)
    {
        s = _s;e = _e;
    }
};

int xmult(Point p0,Point p1,Point p2) //计算p0p1 X p0p2
{
    return (p1 - p0) ^ (p2 - p0);
}

Line line[MAXN];
int ret[MAXN];
int N,M;
int num[MAXN];
double X1,Y1,X2,Y2;
const int cmp(Line a,Line b)
{
    return a.s.x < b.s.x;
}

int main()
{
    bool first = true;
    while (scanf("%d",&N) != EOF)
    {
        if(N == 0) break;
        memset(ret,0,sizeof(ret));
        scanf("%d%lf%lf%lf%lf",&M,&X1,&Y1,&X2,&Y2);
        int UI,LI;
        for (int i = 0 ; i < N ; i++)
        {
            scanf("%d%d",&UI,&LI);
            line[i] = Line(Point(UI,Y1),Point(LI,Y2));
        }
        line[N] = Line(Point(X2,Y1),Point(X2,Y2));
        Point p;
        sort(line ,line + N + 1,cmp);
        memset(ret,0,sizeof(ret));
        while (M--)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            p = Point(x,y);
            int l = 0,r = N;
            int ans;
            while (l <= r)
            {
                int mid = (l + r) / 2;
                if (xmult(p,line[mid].s,line[mid].e) < 0)
                {
                    ans = mid;
                    r = mid - 1;
                }
                else l = mid + 1;
            }
            ret[ans]++;
        }
        for (int i = 1 ; i <= N ; i++)num[i] = 0;
        for (int i = 0 ; i <= N ; i++)
            if (ret[i] > 0) num[ret[i]]++;
        puts("Box");
        for (int i = 1 ; i <= N ; i++)
            if (num[i] > 0) printf("%d: %d\n",i,num[i]);
    }
    return 0;
}

POJ 3304 segments

如果存在这样的直线满足条件,那么可以做这条直线的垂线,那么这条垂线就会

与所有线段相交于是问题转换为询问是否存在一条直线与所有线段相交

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
const int MAXN = 110;
const double eps = 1e-8;
/*如果有存在这样的直线,过投影相交区域作直线的垂线,
该垂线必定与每条线段相交,
问题转化为问是否存在一条线和所有线段相交
*/
int sgn(double x)
{
    if (fabs(x) < eps) return 0;
    if (x < 0) return -1;
    return 1;
}

struct Point
{
    double x,y;
    Point(){}
    Point(double tx,double ty)
    {
        x = tx;
        y = ty;
    }

    Point operator - (const Point &b) const
    {
        return Point(x - b.x,y - b.y);
    }

    double operator ^ (const Point &b) const
    {
        return x * b.y - y * b.x;
    }

    double operator * (const Point &b) const
    {
        return x * b.x + y * b.y;
    }
};

struct Line
{
    Point s,e;
    Line(){}
    Line(Point a,Point b)
    {
        s = a;
        e = b;
    }
};

double xmult(Point p0,Point p1,Point p2)//P0P1 ^ POP2;
{
    return (p1 - p0) ^ (p2 - p0);
}

bool seg_inter_line(Line l1,Line l2)//line l1,seg l2
{
    return sgn(xmult(l2.s,l1.s,l1.e)) * sgn(xmult(l2.e,l1.s,l1.e)) <= 0;
}

double dist(Point a,Point b)
{
    return sqrt((b - a) * (b - a));
}

Line line[MAXN];
bool judge(Line l1,int n)
{
    if (sgn(dist(l1.s,l1.e)) == 0) return false;
    for (int i = 0 ; i < n ; i++)
    {
        if (seg_inter_line(l1,line[i]) == false) return false;
    }
    return true;
}

int main()
{
    int T,n;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d",&n);
        double x1,y1,x2,y2;
        for (int i = 0 ; i < n ; i++)
        {
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            line[i] = Line(Point(x1,y1) ,Point(x2,y2));
        }
        bool flag = false;
        for (int i = 0 ; i < n && !flag ; i++)
            for (int j = 0 ; j < n && !flag ; j++)
        {
            if (judge(Line(line[i].s,line[j].s),n) ||
                judge(Line(line[i].s,line[j].e),n) ||
                judge(Line(line[i].e,line[j].s),n) ||
                judge(Line(line[i].e,line[j].e),n))
            flag = true;
        }
        if (flag) puts("Yes!");
        else puts("No!");
    }
    return false;
}

POJ 1269 Intersecting Lines

直接判断直线相交的情况

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
const double eps = 1e-8;

int sgn(double x)
{
    if (fabs(x) < eps) return 0;
    if (x < 0) return -1;
    return 1;
}

struct Point
{
    double x,y;
    Point(){}
    Point (double tx,double ty)
    {
        x = tx;
        y = ty;
    }

    Point operator - (const Point &b) const
    {
        return Point(x - b.x,y - b.y);
    }

    double operator ^ (const Point &b) const
    {
        return x * b.y - y * b.x;
    }

    double operator * (const Point &b) const
    {
        return x * b.x + y * b.y;
    }
};

struct Line
{
    Point s,e;
    Line(){}
    Line(Point a,Point b)
    {
        s = a;
        e = b;
    }

    pair<Point,int> operator & (const Line b) const
    {
        Point res = s;
        if (sgn((s - e) ^ (b.s - b.e)) == 0)
        {
            if (sgn((b.s - s) ^ (b.e - s)) == 0)
                return make_pair(res,0);//same
            else return make_pair(res,1);//parell
        }
        double tmp = ((s - b.s) ^ (b.s - b.e)) / ((s - e) ^ (b.s - b.e));
        res.x += (e.x - s.x) * tmp;
        res.y += (e.y - s.y) * tmp;
        return make_pair(res,2);
    }
};

int main()
{
    int T;
    scanf("%d",&T);
    printf("INTERSECTING LINES OUTPUT\n");
    while (T--)
    {
        double x1,y1,x2,y2,x3,y3,x4,y4;
        scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&x1,&y1,&x2,&y2,&x3,&y3,&x4,&y4);
        Line line1 = Line(Point(x1,y1),Point(x2,y2));
        Line line2 = Line(Point(x3,y3),Point(x4,y4));
        pair<Point,int> ans = line1 & line2;
        if (ans.second == 2) printf("POINT %.2f %.2f\n",ans.first.x,ans.first.y);
        else if (ans.second == 1) puts("NONE");
        else puts("LINE");
    }
    puts("END OF OUTPUT");
    return 0;
}

POJ 1556 the doors

注意如果线段相交交点是端点的话扔钱可以继续传递

所以题目总有一段特判

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
const double eps = 1e-8;
int sgn(double x)
{
    if (fabs(x) < eps) return 0;
    if (x < 0) return -1;
    return 1;
}

struct Point
{
    double x,y;
    Point(){}
    Point(double tx,double ty)
    {
        x = tx;
        y = ty;
    }

    Point operator - (const Point &b) const
    {
        return Point(x - b.x,y - b.y);
    }

    double operator ^ (const Point &b) const
    {
        return x * b.y - y * b.x;
    }

    double operator * (const Point b) const
    {
        return x * b.x + y * b.y;
    }
};

struct Line
{
    Point s,e;
    Line(){}
    Line(Point a,Point b)
    {
        s = a;
        e = b;
    }
};

bool inter(Line l1,Line l2)
{
    return max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x) &&
        max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x) &&
        max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y) &&
        max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y) &&
        sgn((l2.s - l1.s) ^ (l1.e - l1.s)) * sgn((l2.e - l1.s) ^ (l1.e - l1.s)) <= 0 &&
        sgn((l1.s - l2.s) ^ (l2.e - l2.s)) * sgn((l1.e - l2.s) ^ (l2.e - l2.s)) <= 0;
}

double dist(Point a,Point b)
{
    return sqrt((b - a) * (b - a));
}

const int MAXN = 200;
Line line[MAXN];
double dis[MAXN][MAXN];
const double INF = 1e15;
Point point[MAXN * 2];
int cas,tot;

bool judge(Line cur)
{
    for (int i = 1 ; i <= cas ; i++)
        if (line[i].s.x == cur.s.x || line[i].s.x == cur.e.x) continue;
        else if (inter(cur,line[i])) return false;
    return true;
}

int main()
{
   // freopen("sample.txt","r",stdin);
    int N;
    while (scanf("%d",&N) != EOF)
    {
        if (N == -1) break;
        double x,y1,y2,y3,y4;
        cas = 0;
        tot = 0;
        for (int i = 1 ; i <= N ; i++)
        {
            scanf("%lf%lf%lf%lf%lf",&x,&y1,&y2,&y3,&y4);
            line[++cas] = Line(Point(x,0),Point(x,y1));
            line[++cas] = Line(Point(x,y2),Point(x,y3));
            line[++cas] = Line(Point(x,y4),Point(x,10));
            point[++tot] = Point(x,y1);
            point[++tot] = Point(x,y2);
            point[++tot] = Point(x,y3);
            point[++tot] = Point(x,y4);
        }
        for (int i = 0 ; i < MAXN ; i++)
            for (int j = 0 ; j < MAXN ; j++)
                dis[i][j] = i == j ? 0 : INF;
        for (int i = 1 ; i <= tot ; i++)
        {
            Line tmp = Line(point[i],Point(0,5.0));
            if (judge(tmp)) dis[0][i] = dist(point[i],Point(0,5.0));
        }
       // for (int i = 1 ; i <= tot ; i++)
         //   printf("%.2lf %.2lf %.2lf\n",point[i].x,point[i].y,dis[0][i]);
        for (int i = 1 ; i <= tot ; i++)
        {
            for (int j = 1 ; j <= tot ; j++)
            {
                if (i == j) continue;
                Line tmp = Line(point[i],point[j]);
                if (judge(tmp)) dis[i][j] = dist(point[i],point[j]);
            }
        }
        for (int i = 1 ; i <= tot ; i++)
        {
            Line tmp = Line(point[i],Point(10,5));
            if (judge(tmp)) dis[i][tot + 1] = dist(point[i],Point(10,5));
        }
        Line tmp = Line(Point(0,5),Point(10,5));
        if (judge(tmp)) dis[0][tot + 1] = 10;
        for (int k = 0 ;  k <= tot + 1 ; k++)
        {
            for (int i = 0 ; i <= tot +  1 ; i++)
                for (int j = 0 ; j <= tot + 1 ; j++)
                    dis[i][j] = min(dis[i][j],dis[i][k] + dis[k][j]);
        }
        printf("%.2f\n",dis[0][tot + 1]);
    }
    return 0;
}

POJ 2653 Pick up Sticks

暴力枚举判断线段相交

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
const double eps = 1e-8;
int sgn(double x)
{
    if (fabs(x) < eps) return 0;
    if (x < 0) return -1;
    return 1;
}

struct Point
{
    double x,y;
    Point(){}
    Point(double tx,double ty)
    {
        x = tx;
        y = ty;
    }

    Point operator - (const Point &b) const
    {
        return Point(x - b.x,y - b.y);
    }

    double operator ^ (const Point &b) const
    {
        return x * b.y - y * b.x;
    }

    double operator * (const Point &b) const
    {
        return x * b.x + y * b.y;
    }
};

struct Line
{
    Point s,e;
    Line(){}
    Line(Point a,Point b)
    {
        s = a;
        e = b;
    }
};

bool inter(Line l1,Line l2)
{
    return
        max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x) &&
        max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x) &&
        max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y) &&
        max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y) &&
        sgn((l2.s - l1.s) ^ (l1.e - l1.s)) * sgn((l2.e - l1.s) ^ (l1.e - l1.s)) <= 0 &&
        sgn((l1.s - l2.s) ^ (l2.e - l2.s)) * sgn((l1.e - l2.s) ^ (l2.e - l2.s)) <= 0;
}

const int MAXN = 100010;
Line line[MAXN];
bool flag[MAXN];

int main()
{
    int N;
    while (scanf("%d",&N) != EOF)
    {
        if (N == 0) break;
        memset(flag,false,sizeof(flag));
        for (int i = 1 ; i <= N ; i++)
        {
            double x1,y1,x2,y2;
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            line[i] = Line(Point(x1,y1),Point(x2,y2));
        }
        for (int i = 1 ; i <= N ; i++)
        {
            for (int j = i + 1 ; j <= N ; j++)
            {
                if (inter(line[i],line[j]))
                {
                    flag[i] = true;
                    break;
                }
            }
        }
        printf("Top sticks: ");
        bool first = true;
        for (int i = 1 ; i <= N ; i++)
        {
            if (!flag[i])
            {
                if (first) first = false;
                else printf(", ");
                printf("%d",i);
            }
        }
        puts(".");
    }
    return 0;
}

POJ 1066 Treasure Hunt

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
const double eps = 1e-8;
const int INF = 0x3f3f3f3f;
int sgn(double x)
{
    if (fabs(x) < eps) return 0;
    if (x < 0) return -1;
    return 1;
}

struct Point
{
    double x,y;
    Point(){}
    Point(double tx,double ty)
    {
        x = tx;
        y = ty;
    }

    Point operator - (const Point &b) const
    {
        return Point(x - b.x,y - b.y);
    }

    double operator ^ (const Point &b) const
    {
        return x * b.y - y * b.x;
    }

    double operator * (const Point &b) const
    {
        return x * b.x + y * b.y;
    }

    void transxy(double B) //
    {
        double tx = x;
        double ty = y;
        x = tx * cos(B) - ty * sin(B);
        y = ty * sin(B) + tx * cos(B);
    }
};

struct Line
{
    Point s,e;
    Line(){}
    Line(Point a,Point b)
    {
        s = a;
        e = b;
    }

    pair<int,Point> operator & (const Line &b) const
    {
        Point res = s;
        if (sgn((s - e) ^ (b.s - b.e)) == 0)
        {
            if (sgn((s - b.e) ^ (b.s - b.e)) == 0)
                return make_pair(0,res);
            else return make_pair(1,res);
        }
        double t = ((s - b.s) ^ (b.s - b.e)) / ((s - e) ^ (b.s - b.e));
        res.x += (e.x - s.x) * t;
        res.y += (e.y - s.y) * t;
        return make_pair(2,res);
    }
};

double dist(Point a,Point b)
{
    return sqrt((b - a) * (b - a));
}

bool inter(Line l1,Line l2)
{
     return max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x) &&
        max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x) &&
        max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y) &&
        max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y) &&
        sgn((l2.s - l1.s) ^ (l1.e - l1.s)) * sgn((l2.e - l1.s) ^ (l1.e - l1.s)) <= 0 &&
        sgn((l1.s - l2.s) ^ (l2.e - l1.s)) * sgn((l1.e - l2.s) ^ (l2.e - l2.s)) <= 0;
}

const int MAXN = 110;
Line line[MAXN];
Point s;
Point p[MAXN];
int cas;

int main()
{
    int n;
    while (scanf("%d",&n) != EOF)
    {
        cas = 0;
        double x1,y1,x2,y2;
        for (int i = 1 ; i <= n ; i++)
        {
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            line[i] = Line(Point(x1,y1),Point(x2,y2));
            p[++cas] = Point(x1,y1);
            p[++cas] = Point(x2,y2);
        }
        scanf("%lf%lf",&x1,&y1);
        s = Point(x1,y1);;
        int ans = INF;
        for (int i = 1 ; i <= cas;  i++)
        {
            int cnt = 0;
            Line tmp = Line(s,p[i]);
            for (int j = 1 ; j <= n ; j++)
                if (inter(tmp,line[j])) cnt++;
            ans = min(ans,cnt);
        }
        Line tmp;
        tmp = Line(s,Point(0,0));
        int cnt = 0;
        for (int j = 1 ; j <= n ; j++)
            if (inter(tmp,line[j])) cnt++;
        ans = min(ans,cnt + 1);

        tmp = Line(s,Point(0,100));
        cnt = 0;
        for (int j = 1 ; j <= n ; j++)
            if (inter(tmp,line[j])) cnt++;
        ans = min(ans,cnt + 1);

        tmp = Line(s,Point(100,0));
        cnt = 0;
        for (int j = 1 ; j <= n ; j++)
            if (inter(tmp,line[j])) cnt++;
        ans = min(ans,cnt + 1);

        tmp = Line(s,Point(100,100));
        cnt = 0;
        for (int j = 1 ; j <= n ; j++)
            if (inter(tmp,line[j])) cnt++;
        ans = min(ans,cnt + 1);
        printf("Number of doors = %d\n",ans);
    }
    return 0;
}

POJ 1410 Intersection

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
const double eps = 1e-6;
int sgn(double x)
{
    if (fabs(x) < eps) return 0;
    if (x < 0) return -1;
    return 1;
}

struct Point
{
    double x,y;
    Point(){}
    Point(double tx,double ty)
    {
        x = tx;
        y = ty;
    }

    Point operator - (const Point &b) const
    {
        return Point(x - b.x,y - b.y);
    }

    double operator ^ (const Point &b) const
    {
        return x * b.y - y * b.x;
    }

    double operator * (const Point &b) const
    {
        return x * b.x + y * b.y;
    }

    void transxy(double B)
    {
        double tx = x;
        double ty = y;
        x = tx * cos(B) - ty * sin(B);
        y = tx * sin(B) + ty * cos(B);
    }
};

struct Line
{
    Point s,e;
    Line(){}
    Line(Point a,Point b)
    {
        s = a;
        e = b;
    }

    pair<int,Point> operator & (const Line &b) const
    {
        Point res = s;
        if (sgn((s - e) ^ (b.s - b.e)) == 0)
        {
            if (sgn((s - b.e) ^ (b.s - b.e)) == 0)
                return make_pair(0,res);
            else return make_pair(1,res);
        }
        double t = ((s - b.s) ^ (b.s - b.e)) / ((s - e) ^ (b.s - b.e));
        res.x += (e.x - s.x) * t;
        res.y += (e.y - s.y) * t;
        return make_pair(2,res);
    }
};

bool inter(Line l1,Line l2)
{
     return max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x) &&
        max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x) &&
        max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y) &&
        max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y) &&
        sgn((l2.s - l1.s) ^ (l1.e - l1.s)) * sgn((l2.e - l1.s) ^ (l1.e - l1.s)) <= 0 &&
        sgn((l1.s - l2.s) ^ (l2.e - l1.s)) * sgn((l1.e - l2.s) ^ (l2.e - l2.s)) <= 0;
}

bool OnSeg(Point P,Line L)
{
    return
    sgn((L.s-P)^(L.e-P)) == 0 &&
    sgn((P.x - L.s.x) * (P.x - L.e.x)) <= 0 &&
    sgn((P.y - L.s.y) * (P.y - L.e.y)) <= 0;
}

//判断点在凸多边形内
//点形成一个凸包,而且按逆时针排序(如果是顺时针把里面的<0改为>0)
//点的编号:0~n-1
//返回值:
//-1:点在凸多边形外
//0:点在凸多边形边界上
//1:点在凸多边形内
int inConvexPoly(Point a,Point p[],int n)
{
    for(int i = 0 ; i < n ; i++)
    {
        if(sgn((p[i] - a) ^ (p[(i + 1) % n] - a)) < 0)return -1;
        else if(OnSeg(a,Line(p[i],p[(i + 1) % n])))return 0;
    }
    return 1;
}

//判断点在任意多边形内
//射线法,poly[]的顶点数要大于等于3,点的编号0~n-1
//返回值
//-1:点在凸多边形外
//0:点在凸多边形边界上
//1:点在凸多边形内
int inPoly(Point p,Point poly[],int n)
{
    int cnt;
    Line ray,side;
    cnt = 0;
    ray.s = p;
    ray.e.y = p.y;
    ray.e.x = -100000000000.0;//-INF,注意取值防止越界

    for(int i = 0;i < n;i++)
    {
        side.s = poly[i];
        side.e = poly[(i+1)%n];

        if(OnSeg(p,side))return 0;

        //如果平行轴则不考虑
        if(sgn(side.s.y - side.e.y) == 0)
            continue;

        if(OnSeg(side.s,ray))
        {
            if(sgn(side.s.y - side.e.y) > 0)cnt++;
        }
        else if(OnSeg(side.e,ray))
        {
            if(sgn(side.e.y - side.s.y) > 0)cnt++;
        }
        else if(inter(ray,side))
            cnt++;
    }
    if(cnt % 2 == 1)return 1;
    else return -1;
}

int main()
{
    int T;
    scanf("%d",&T);
    while (T--)
    {
        double x1,y1,x2,y2;
        scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
        Line line = Line(Point(x1,y1),Point(x2,y2));
        scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
        if (x1 > x2) swap(x1,x2);
        if (y1 > y2) swap(y1,y2);
        Point tmp[10];
        tmp[0] = Point(x1,y1);
        tmp[1] = Point(x2,y1);
        tmp[2] = Point(x2,y2);
        tmp[3] = Point(x1,y2);
        bool flag = false;
        if (inter(line,Line(tmp[0],tmp[1]))) flag = true;
        if (inter(line,Line(tmp[1],tmp[2]))) flag = true;
        if (inter(line,Line(tmp[2],tmp[3]))) flag = true;
        if (inter(line,Line(tmp[3],tmp[0]))) flag = true;
        if (inConvexPoly(line.s,tmp,4) >= 0 && inConvexPoly(line.e,tmp,4) >= 0) flag = true;
        printf("%s\n",flag ? "T" : "F");
    }
    return 0;
}

****POJ 1696 Space Ant

这个题目涉及到极角排序,首先题意一只蚂蚁,只会向左转,现在给出平面上很多个点,求解一种走法,
能使得蚂蚁能经过的点最多,每个顶点该蚂蚁只能经过一次,且所行走的路线不能发生交叉.

那么可想到的方案就是最先找到Y坐标最小的点,每次尽量选择靠下方的点走。

所以涉及到当前所在点对其他未到达点的角度问题。kuangbin神用的排序方式很好。MARK学习下

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
const double eps = 1e-8;
int sgn(double x)
{
    if (fabs(x) < eps) return 0;
    if (x < 0) return -1;
    return 1;
}

struct Point
{
    double x,y;
    int idx;
    Point(){}
    Point(double tx,double ty)
    {
        x = tx;
        y = ty;
    }

    Point operator - (const Point &b) const
    {
        return Point(x - b.x,y - b.y);
    }

    double operator ^ (const Point &b) const
    {
        return x * b.y - y * b.x;
    }

    double operator * (const Point &b) const
    {
        return x * b.x + y * b.y;
    }
};

double dist(Point a,Point b)
{
    return sqrt((b - a) * (b - a));
}

const int MAXN = 110;
Point p[MAXN];
int pos;
bool cmp(Point a,Point b)//对p[pos]点计较排序
{
    double tmp = (a - p[pos]) ^ (b - p[pos]);
    if (sgn(tmp) == 0)
        return dist(p[pos],a) < dist(p[pos],b);
    else if (sgn(tmp) < 0) return false;
    else return true;
}

int main()
{
    int T;
    scanf("%d",&T);
    while (T--)
    {
        int n;
        scanf("%d",&n);
        for (int i = 0 ; i < n ; i++)
        {
            scanf("%d%lf%lf",&p[i].idx,&p[i].x,&p[i].y);
            if (i != 0) if (p[i].y < p[0].y || (p[i].y == p[0].y && p[i].x < p[0].x))
                swap(p[0],p[i]);
        }
        pos = 0;
        for (int i = 1 ; i < n ; i++)
        {
            sort(p + i,p + n,cmp);
            pos++;
        }
        printf("%d",n);
        for (int i = 0 ; i < n ; i++)
            printf(" %d",p[i].idx);
        puts("");
    }
    return 0;
}

****POJ 3347 Kadj Squares

这个题挺厉害,首先可以直接解出每个正方形左右端点的横坐标。然后就化为区间覆盖问题

接触横坐标其实很简单。就是化为区间覆盖他的维护方式很厉害

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
const int MAXN = 110;
struct node
{
    int l,r;
    int len;
}src[MAXN];
bool del[MAXN];
int N;

int main()
{
    while (scanf("%d",&N) != EOF)
    {
        if (N == 0) break;
        for (int i = 1 ; i <= N ; i++)
        {
            scanf("%d",&src[i].len);
            src[i].l = 0;
            for (int j = 1 ; j < i ; j++)
                src[i].l = max(src[i].l,src[j].r - abs(src[i].len - src[j].len));
            src[i].r = src[i].l + 2 *  src[i].len;
        }
        //for (int i = 1 ; i <= N ; i++)printf("%d %d\n",src[i].l,src[i].r);
        memset(del,false,sizeof(del));
        for (int i = 1 ; i <= N ; i++)
        {
            for (int j = 1 ; j < i ; j++)
            {
                if (src[i].l < src[j].r && src[i].len < src[j].len)
                    src[i].l = src[j].r;
            }
            for (int j = i + 1 ; j <= N ; j++)
            {
                if (src[i].r > src[j].l && src[i].len < src[j].len)
                    src[i].r = src[j].l;
            }
        }
        bool first = true;
        for (int i = 1 ; i <= N ; i++)
        {
            if (src[i].l < src[i].r)
            {
                if (first) first = false;
                else putchar(‘ ‘);
                printf("%d",i);
            }
        }
        puts("");
    }
    return 0;
}

POJ 2826 An Easy Problem?!

这道题就是要仔细一点有多重情况

利用线段相交判定是否这个形状的图形被封住了一点水也装不下

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
const double eps = 1e-8;
const int INF = 1000000;
int sgn(double x)
{
    if (fabs(x) < eps) return 0;
    if (x < 0) return -1;
    return 1;
}

struct Point
{
    double x,y;
    Point(){}
    Point(double tx,double ty)
    {
        x = tx;
        y = ty;
    }

    Point operator - (const Point &b) const
    {
        return Point(x - b.x,y - b.y);
    }

    double operator ^ (const Point &b) const
    {
        return x * b.y - y * b.x;
    }

    double operator * (const Point &b) const
    {
        return x * b.x + y * b.y;
    }
};

struct Line
{
    Point s,e;
    Line(){}
    Line(Point a,Point b)
    {
        s = a;
        e = b;
    }

    pair<int,Point> operator &(const Line &b)const
    {
        Point res = s;
        if(sgn((s - e) ^ (b.s - b.e)) == 0)
        {
            if(sgn((s - b.e) ^ (b.s - b.e)) == 0)
                return make_pair(0,res);//重合
            else return make_pair(1,res);//平行
        }
        double t = ((s - b.s) ^ (b.s - b.e)) / ((s - e) ^ (b.s - b.e));
        res.x += (e.x - s.x) * t;
        res.y += (e.y - s.y) * t;
        return make_pair(2,res);
    }
};

bool inter(Line l1,Line l2)
{
    return
    max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x) &&
    max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x) &&
    max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y) &&
    max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y) &&
    sgn((l2.s - l1.e) ^ (l1.s - l1.e)) * sgn((l2.e - l1.e) ^ (l1.s - l1.e)) <= 0 &&
    sgn((l1.s - l2.e) ^ (l2.s - l2.e)) * sgn((l1.e - l2.e) ^ (l2.s - l2.e)) <= 0;
}

int main()
{
    int x1,y1,x2,y2,x3,y3,x4,y4;
    Line l1,l2;
    int T;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d%d%d%d%d%d%d%d",&x1,&y1,&x2,&y2,&x3,&y3,&x4,&y4);
        l1 = Line(Point(x1,y1),Point(x2,y2));
        l2 = Line(Point(x3,y3),Point(x4,y4));
        if ((sgn(l1.s.y - l1.e.y) == 0) ||  (sgn(l2.s.y - l2.e.y) == 0))
        {
            puts("0.00");
            continue;
        }
        if (sgn(l1.s.y - l1.e.y) < 0) swap(l1.s,l1.e);
        if (sgn(l2.s.y - l2.e.y) < 0) swap(l2.s,l2.e);
        if (inter(l1,l2) == false)
        {
            puts("0.00");
            continue;
        }
        if (inter(Line(l1.s,Point(l1.s.x,INF)),l2) == true)
        {
            puts("0.00");
            continue;
        }
        if (inter(Line(l2.s,Point(l2.s.x,INF)),l1) == true)
        {
            puts("0.00");
            continue;
        }
        pair<int,Point>res;
        double area;
        res = l1 & l2;
        Point ret = res.second;
        res = l1 & Line(Point(INF,l2.s.y),l2.s);
        Point ret1 = res.second;
        area = fabs(((l2.s - ret) ^ (ret1 - ret)) / 2.0);
        res = l2 & Line(Point(INF,l1.s.y),l1.s);
        Point ret2 = res.second;
        area = min(area,fabs(((l1.s - ret) ^ (ret2 - ret)) / 2.0));
        printf("%.2f\n",area + eps);
    }
    return 0;
}

POJ 1039 Pipe

直接暴力枚举2个点即可

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
const double eps = 1e-8;
const double INF = 1e14;
int sgn(double x)
{
    if (fabs(x) < eps) return 0;
    if (x < 0) return -1;
    return 1;
}

struct Point
{
    double x,y;
    Point(){}
    Point(double tx,double ty)
    {
        x = tx;
        y = ty;
    }

    Point operator - (const Point &b) const
    {
        return Point(x - b.x,y - b.y);
    }

    double operator ^ (const Point &b) const
    {
        return x * b.y - y * b.x;
    }

    double operator * (const Point &b) const
    {
        return x * b.x + y * b.y;
    }
};

struct Line
{
    Point s,e;
    Line(){}
    Line(Point a,Point b)
    {
        s = a;
        e = b;
    }

    pair<int,Point> operator &(const Line &b)const
    {
        Point res = s;
        if(sgn((s - e) ^ (b.s - b.e)) == 0)
        {
            if(sgn((s - b.e) ^ (b.s - b.e)) == 0)
                return make_pair(0,res);//重合
            else return make_pair(1,res);//平行
        }
        double t = ((s - b.s) ^ (b.s - b.e)) / ((s - e) ^ (b.s - b.e));
        res.x += (e.x - s.x) * t;
        res.y += (e.y - s.y) * t;
        return make_pair(2,res);
    }
};

bool seg_inter_line(Line l1,Line l2) //line l1.seg l2;
{
    return sgn((l2.s - l1.e) ^ (l1.s - l1.e)) * sgn((l2.e - l1.e) ^ (l1.s - l1.e)) <= 0;
}

const int MAXN = 110;
Point up[MAXN],down[MAXN];
int n;

int main()
{
    while (scanf("%d",&n) != EOF)
    {
        if (n == 0) break;
        for (int i = 0 ; i < n ; i++)
        {
            scanf("%lf%lf",&up[i].x,&up[i].y);
            down[i] = up[i];
            down[i].y--;
        }
        bool flag = false;
        double ans = -INF;
        int k;
        for (int i = 0 ; i < n && !flag ; i++)
        {
            for (int j = i + 1 ; j < n && !flag ; j++)
            {
                for (k = 0 ; k < n ; k++)
                {
                    if (seg_inter_line(Line(up[i],down[j]),Line(up[k],down[k])) == false)
                        break;
                }
                if (k >= n)
                {
                    flag = true;
                    break;
                }
                if (k > max(i,j))
                {
                    if (seg_inter_line(Line(up[i],down[j]),Line(up[k - 1],up[k])))
                    {
                        pair<int,Point>ret = Line(up[i],down[j]) & Line(up[k - 1],up[k]);
                        ans = max(ans,ret.second.x);
                    }
                    if (seg_inter_line(Line(up[i],down[j]),Line(down[k - 1],down[k])))
                    {
                        pair<int,Point>ret = Line(up[i],down[j]) & Line(down[k - 1],down[k]);
                        ans = max(ans,ret.second.x);
                    }
                }

                for (k = 0 ; k < n ; k++)
                {
                    if (seg_inter_line(Line(down[i],up[j]),Line(down[k],up[k])) == false)
                        break;
                }
                if (k >= n)
                {
                    flag = true;
                    break;
                }
                if (k > max(i,j))
                {
                    if (seg_inter_line(Line(down[i],up[j]),Line(up[k],up[k - 1])) == true)
                    {
                        pair<int,Point>ret = Line(down[i],up[j]) & Line(up[k],up[k - 1]);
                        ans = max(ans,ret.second.x);
                    }
                    if (seg_inter_line(Line(down[i],up[j]),Line(down[k],down[k - 1])) == true)
                    {
                        pair<int,Point>ret = Line(down[i],up[j]) & Line(down[k],down[k - 1]);
                        ans = max(ans,ret.second.x);
                    }
                }
            }
        }
        if (flag) puts("Through all the pipe.");
        else printf("%.2f\n",ans);
    }
    return 0;
}

POJ 3449 Geometric Shapes

暴力判相交。这里有个知识

**给出坐标轴上1个正方形对角线上的2个点

求另外2个点的最简单方法

这4个方程可解

x1+x3 = x0+x2;

x1-x3  =  y2-y0;

y1+y3 =  y0+y2;

y1-y3 =  x0-x2;

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
const double eps = 1e-8;
int sgn(double x)
{
    if (fabs(x) < eps) return 0;
    if (x < 0) return -1;
    return 1;
}

struct Point
{
    double x,y;
    Point(){}
    Point(double tx,double ty)
    {
        x = tx;
        y = ty;
    }

    Point operator - (const Point &b) const
    {
        return Point(x - b.x,y - b.y);
    }

    double operator ^ (const Point &b) const
    {
        return x * b.y - y * b.x;
    }

    double operator * (const Point &b) const
    {
        return x * b.x + y * b.y;
    }
};

struct Line
{
    Point s,e;
    Line(){}
    Line(Point a,Point b)
    {
        s = a;
        e = b;
    }
};

bool inter(Line l1,Line l2)
{
    return
    max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x) &&
    max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x) &&
    max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y) &&
    max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y) &&
    sgn((l2.s - l1.e) ^ (l1.s - l1.e)) * sgn((l2.e - l1.e) ^ (l1.s - l1.e)) <= 0 &&
    sgn((l1.s - l2.e) ^ (l2.s - l2.e)) * sgn((l1.e - l2.e) ^ (l2.s - l2.e)) <= 0;
}

const int MAXN = 30;
struct node
{
    char id;
    int n;
    Point p[MAXN];
    friend bool operator < (const node &a,const node &b)
    {
        return a.id < b.id;
    }
}src[MAXN];

char str[MAXN];
bool check(node a,node b)
{
    for (int i = 0 ; i < a.n ; i++)
    {
        for (int j = 0 ; j < b.n ; j++)
        {
            if (inter(Line(a.p[i],a.p[(i + 1) % a.n]),Line(b.p[j],b.p[(j + 1) % b.n])))
                return true;
        }
    }
    return false;
}

bool flag[MAXN];
int main()
{
    int n;
    while (scanf("%s",str) != EOF)
    {
        if (str[0] == ‘.‘) break;
        n = 0;
        src[0].id = str[0];
        scanf("%s",str);
        if (strcmp(str,"square") == 0)
        {
            src[0].n = 4;
            scanf(" (%lf,%lf)",&src[0].p[0].x,&src[0].p[0].y);
            scanf(" (%lf,%lf)",&src[0].p[2].x,&src[0].p[2].y);
            src[0].p[1].x = ((src[0].p[0].x + src[0].p[2].x) + (src[0].p[2].y - src[0].p[0].y)) / 2;
            src[0].p[1].y = ((src[0].p[0].y + src[0].p[2].y) + (src[0].p[0].x - src[0].p[2].x)) / 2;
            src[0].p[3].x = ((src[0].p[0].x + src[0].p[2].x) - (src[0].p[2].y - src[0].p[0].y)) / 2;
            src[0].p[3].y = ((src[0].p[0].y + src[0].p[2].y) - (src[0].p[0].x - src[0].p[2].x)) / 2;
        }
        else if (strcmp(str,"line") == 0)
        {
            src[0].n = 2;
            scanf(" (%lf,%lf)",&src[0].p[0].x,&src[0].p[0].y);
            scanf(" (%lf,%lf)",&src[0].p[1].x,&src[0].p[1].y);
        }
        else if (strcmp(str,"triangle") == 0)
        {
            src[0].n = 3;
            scanf(" (%lf,%lf)",&src[0].p[0].x,&src[0].p[0].y);
            scanf(" (%lf,%lf)",&src[0].p[1].x,&src[0].p[1].y);
            scanf(" (%lf,%lf)",&src[0].p[2].x,&src[0].p[2].y);
        }
        else if (strcmp(str,"rectangle") == 0)
        {
            src[0].n = 4;
            scanf(" (%lf,%lf)",&src[0].p[0].x,&src[0].p[0].y);
            scanf(" (%lf,%lf)",&src[0].p[1].x,&src[0].p[1].y);
            scanf(" (%lf,%lf)",&src[0].p[2].x,&src[0].p[2].y);
            src[0].p[3].x = src[0].p[2].x + src[0].p[0].x - src[0].p[1].x;
            src[0].p[3].y = src[0].p[2].y + src[0].p[0].y - src[0].p[1].y;
        }
        else if(strcmp(str,"polygon") == 0)
        {
            scanf("%d",&src[0].n);
            for (int i = 0 ; i <= src[0].n ; i++)
                scanf(" (%lf,%lf)",&src[0].p[i].x,&src[0].p[i].y);
        }
        n = 1;
        while (scanf("%s",str) != EOF)
        {
            if (str[0] == ‘-‘) break;
            src[n].id = str[0];
            scanf("%s",str);
            if (strcmp(str,"square") == 0)
            {
                src[n].n = 4;
                scanf(" (%lf,%lf)",&src[n].p[0].x,&src[n].p[0].y);
                scanf(" (%lf,%lf)",&src[n].p[2].x,&src[n].p[2].y);
                src[n].p[1].x = ((src[n].p[0].x + src[n].p[2].x) + (src[n].p[2].y - src[n].p[0].y)) / 2;
                src[n].p[1].y = ((src[n].p[0].y + src[n].p[2].y) + (src[n].p[0].x - src[n].p[2].x)) / 2;
                src[n].p[3].x = ((src[n].p[0].x + src[n].p[2].x) - (src[n].p[2].y - src[n].p[0].y)) / 2;
                src[n].p[3].y = ((src[n].p[0].y + src[n].p[2].y) - (src[n].p[0].x - src[n].p[2].x)) / 2;
            }
            else if (strcmp(str,"line") == 0)
            {
                src[n].n = 2;
                scanf(" (%lf,%lf)",&src[n].p[0].x,&src[n].p[0].y);
                scanf(" (%lf,%lf)",&src[n].p[1].x,&src[n].p[1].y);
            }
            else if (strcmp(str,"triangle") == 0)
            {
                src[n].n = 3;
                scanf(" (%lf,%lf)",&src[n].p[0].x,&src[n].p[0].y);
                scanf(" (%lf,%lf)",&src[n].p[1].x,&src[n].p[1].y);
                scanf(" (%lf,%lf)",&src[n].p[2].x,&src[n].p[2].y);
            }
            else if (strcmp(str,"rectangle") == 0)
            {
                src[n].n = 4;
                scanf(" (%lf,%lf)",&src[n].p[0].x,&src[n].p[0].y);
                scanf(" (%lf,%lf)",&src[n].p[1].x,&src[n].p[1].y);
                scanf(" (%lf,%lf)",&src[n].p[2].x,&src[n].p[2].y);
                src[n].p[3].x = src[n].p[2].x + src[n].p[0].x - src[n].p[1].x;
                src[n].p[3].y = src[n].p[2].y + src[n].p[0].y - src[n].p[1].y;
            }
            else if(strcmp(str,"polygon") == 0)
            {
                scanf("%d",&src[n].n);
                for (int i = 0 ; i <= src[n].n ; i++)
                    scanf(" (%lf,%lf)",&src[n].p[i].x,&src[n].p[i].y);
            }
            n++;
        }
        sort(src,src + n);
        for (int i = 0 ; i < n ; i++)
        {
            printf("%c ",src[i].id);
            memset(flag,false,sizeof(flag));
            int cnt = 0;
            for (int j = 0 ; j < n ; j++)
            {
                if (i == j) continue;
                if (check(src[i],src[j]))
                {
                    cnt++;
                    flag[j] = true;
                }
            }
            if (cnt == 0) puts("has no intersections");
            else if (cnt == 1)
            {
                printf("intersects with ");
                for (int j = 0 ; j < n ; j++)
                {
                    if (flag[j])
                    {
                        printf("%c\n",src[j].id);
                        break;
                    }
                }
            }
            else if (cnt == 2)
            {
                printf("intersects with ");
                for (int j = 0 ; j < n ; j++)
                {
                    if (flag[j])
                    {
                        if(cnt == 2)printf("%c ",src[j].id);
                        if(cnt == 1)printf("and %c\n",src[j].id);
                        cnt--;
                    }
                }
            }
            else
            {
                printf("intersects with ");
                for (int j = 0 ; j < n ; j++)
                {
                    if (flag[j])
                    {
                        if(cnt > 1)printf("%c, ",src[j].id);
                        if(cnt == 1)printf("and %c\n",src[j].id);
                        cnt--;
                    }
                }
            }
        }
        puts("");
    }
    return 0;
}

POJ 1584 A Round Peg in a Ground Hole

凸多边形判定通过点到直线距离判园是否在凸多边形内

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
const double eps = 1e-8;
int sgn(double x)
{
    if (fabs(x) < eps) return 0;
    if (x < 0) return -1;
    return 1;
}

struct Point
{
    double x,y;
    Point(){}
    Point(double tx,double ty)
    {
        x = tx;
        y = ty;
    }

    Point operator - (const Point &b) const
    {
        return Point(x - b.x,y - b.y);
    }

    double operator ^ (const Point &b) const
    {
        return x * b.y - y * b.x;
    }

    double operator * (const Point &b)const
    {
        return x * b.x + y * b.y;
    }
};

struct Line
{
    Point s,e;
    Line(){}
    Line(Point a,Point b)
    {
        s = a;
        e = b;
    }
};

double dist(Point a,Point b)
{
    return sqrt((b - a) * (b - a));
}

//判断凸多边形
//允许共线边
//点可以是顺时针给出也可以是逆时针给出
//点的编号1~n-1
bool isconvex(Point poly[],int n)
{
    bool s[3];
    memset(s,false,sizeof(s));
    for(int i = 0;i < n;i++)
    {
        s[sgn( (poly[(i + 1) % n]-poly[i]) ^ (poly[(i + 2) % n] - poly[i]) ) + 1] = true;
        if(s[0] && s[2])return false;
    }
    return true;
}

//点到线段的距离
//返回点到线段最近的点
Point NearestPointToLineSeg(Point P,Line L)
{
    Point result;
    double t = ((P - L.s)*(L.e - L.s)) / ((L.e - L.s)*(L.e - L.s));
    if(t >= 0 && t <= 1)
    {
        result.x = L.s.x + (L.e.x - L.s.x) * t;
        result.y = L.s.y + (L.e.y - L.s.y) * t;
    }
    else
    {
        if(dist(P,L.s) < dist(P,L.e))
            result = L.s;
        else result = L.e;
    }
    return result;
}

//*判断点在线段上
bool OnSeg(Point P,Line L)
{
    return
    sgn((L.s-P)^(L.e-P)) == 0 &&
    sgn((P.x - L.s.x) * (P.x - L.e.x)) <= 0 &&
    sgn((P.y - L.s.y) * (P.y - L.e.y)) <= 0;
}

//*判断点在凸多边形内
//点形成一个凸包,而且按逆时针排序(如果是顺时针把里面的<0改为>0)
//点的编号:0~n-1
//返回值:
//-1:点在凸多边形外
//0:点在凸多边形边界上
//1:点在凸多边形内
int inConvexPoly(Point a,Point p[],int n)
{
    for(int i = 0 ; i < n ; i++)
    {
        if(sgn((p[i] - a) ^ (p[(i + 1) % n] - a)) < 0)return -1;
        else if(OnSeg(a,Line(p[i],p[(i + 1) % n])))return 0;
    }
    return 1;
}

bool inter(Line l1,Line l2)
{
    return
    max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x) &&
    max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x) &&
    max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y) &&
    max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y) &&
    sgn((l2.s - l1.e) ^ (l1.s - l1.e)) * sgn((l2.e - l1.e) ^ (l1.s - l1.e)) <= 0 &&
    sgn((l1.s - l2.e) ^ (l2.s - l2.e)) * sgn((l1.e - l2.e) ^ (l2.s - l2.e)) <= 0;
}

    //*判断点在任意多边形内
//射线法,poly[]的顶点数要大于等于3,点的编号0~n-1
//返回值
//-1:点在凸多边形外
//0:点在凸多边形边界上
//1:点在凸多边形内
int inPoly(Point p,Point poly[],int n)
{
    int cnt;
    Line ray,side;
    cnt = 0;
    ray.s = p;
    ray.e.y = p.y;
    ray.e.x = -100000000000.0;//-INF,注意取值防止越界

    for(int i = 0;i < n;i++)
    {
        side.s = poly[i];
        side.e = poly[(i+1)%n];

        if(OnSeg(p,side))return 0;

        //如果平行轴则不考虑
        if(sgn(side.s.y - side.e.y) == 0)
            continue;

        if(OnSeg(side.s,ray))
        {
            if(sgn(side.s.y - side.e.y) > 0)cnt++;
        }
        else if(OnSeg(side.e,ray))
        {
            if(sgn(side.e.y - side.s.y) > 0)cnt++;
        }
        else if(inter(ray,side))
            cnt++;
    }
    if(cnt % 2 == 1)return 1;
    else return -1;
}

const int MAXN = 110;
Point src[MAXN];
int n;

int main()
{
    double R,X,Y;
    while (scanf("%d",&n) != EOF)
    {
        if (n < 3) break;
        scanf("%lf%lf%lf",&R,&X,&Y);
        for (int i = 0 ; i < n ; i++)
            scanf("%lf%lf",&src[i].x,&src[i].y);
        if (!isconvex(src,n))
        {
            printf("HOLE IS ILL-FORMED\n");
            continue;
        }
        Point P = Point(X,Y);
        if(inPoly(P,src,n) < 0)
        {
            printf("PEG WILL NOT FIT\n");
            continue;
        }
        bool flag = true;
        for (int i = 0 ; i < n ; i++)
        {
            if(sgn(dist(P,NearestPointToLineSeg(P,Line(src[i],src[(i + 1) % n]))) - R) < 0 )
            {
                flag = false;
                break;
            }
        }
        if(flag)printf("PEG WILL FIT\n");
        else printf("PEG WILL NOT FIT\n");
    }
    return 0;
}

时间: 2024-11-10 08:46:03

Kuangbin 带你飞-基础计算几何专题 题解的相关文章

Kuangbin 带你飞-线段树专题 题解

HDU 1166 敌兵布阵 单调更新区间查询和 #include <map> #include <set> #include <list> #include <cmath> #include <ctime> #include <deque> #include <stack> #include <queue> #include <cctype> #include <cstdio> #inc

[kuangbin带你飞]之&#39;最小生成树 &#39;专题(未完成)

带飞网址: https://vjudge.net/article/187 专题六: POJ 1251 Jungle RoadsPOJ 1287 NetworkingPOJ 2031 Building a Space StationPOJ 2421 Constructing RoadsZOJ 1586 QS NetworkPOJ 1789 Truck HistoryPOJ 2349 Arctic NetworkPOJ 1751 HighwaysPOJ 1258 Agri-NetPOJ 3026 B

kuangbin带你飞----线段树专题一(基础操作,单点,区间更新和查询)

A 题意:给出q个询问,单点更新和查询 主要是注意模板的书写 #include<iostream> #include<cstring> #include<algorithm> #include<cmath> #include<cstdlib> #include<climits> #include<stack> #include<vector> #include<queue> #include<

[kuangbin带你飞] 基础DP 题集

题目链接:https://vjudge.net/contest/342715 第一题:A - Max Sum Plus Plus   第二题:B - Ignatius and the Princess IV 题意:给n个数字,n为奇数,求一个数字x,x的个数大于等于(n+1)/2 解法一:map容器 思路:n的范围为1000000,但是元素x值不明,所以我们用map的第一个元素去存x,第二个元素存x的次数 代码: #include<bits/stdc++.h> #include<map&

kuangbin带你飞专题一 简单搜索 题解

目录 [kuangbin带你飞]专题一 简单搜索 [kuangbin带你飞]专题一 简单搜索 总结:用时2天半终于把这个专题刷完了 对于最基础的dfs bfs 路径打印 状态转移也有了一点自己些微的理解 其实2天半可以压缩到1天半的 主要是自己太懒了...慢慢加油刷bin神的专题呀 从大二下学期开始学算法 一开始就知道这个专题 一开始对于这个专题里的所有问题感觉都好难啊..就直接放弃了 看lrj的书 现在看到这个专题还挺唏嘘的吧 突然觉得思维和想法也不是很难 果然是那个时候心不静&还是储量不够吗

「kuangbin带你飞」专题十二 基础DP

layout: post title: 「kuangbin带你飞」专题十二 基础DP author: "luowentaoaa" catalog: true tags: mathjax: true - kuangbin - 动态规划 传送门 A.HDU1024 Max Sum Plus Plus 题意 给你N个数,然后你分成M个不重叠部分,并且这M个不重叠部分的和最大. 思路 动态规划最大m字段和,dp数组,dp[i][j]表示以a[j]结尾的,i个字段的最大和 两种情况:1.第a[j

「kuangbin带你飞」专题十八 后缀数组

layout: post title: 「kuangbin带你飞」专题十八 后缀数组 author: "luowentaoaa" catalog: true tags: - kuangbin - 字符串 - 后缀数组 传送门 倍增法 struct DA{ bool cmp(int *r,int a,int b,int l){ return r[a]==r[b]&&r[a+l]==r[b+l]; } int t1[maxn],t2[maxn],c[maxn]; int r

「kuangbin带你飞」专题二十二 区间DP

layout: post title: 「kuangbin带你飞」专题二十二 区间DP author: "luowentaoaa" catalog: true tags: - kuangbin - 区间DP - 动态规划 传送门 B.LightOJ - 1422 Halloween Costumes 题意 按顺序参加舞会,参加一个舞会要穿一种衣服,可以在参加完一个舞会后套上另一个衣服再去参加舞会,也可以在参加一个舞会的时候把外面的衣服脱了,脱到合适的衣服,但是脱掉的衣服不能再穿,参加完

「kuangbin带你飞」专题二十 斜率DP

layout: post title: 「kuangbin带你飞」专题二十 斜率DP author: "luowentaoaa" catalog: true tags: mathjax: true - kuangbin - 动态规划 - 斜率DP 传送门 A.HDU - 3507 Print Article 题意 就是输出序列a[n],每连续输出的费用是连续输出的数字和的平方加上常数M 让我们求这个费用的最小值. 题解 概率DP的入门题,把我搞得要死要活的. 首先dp[i]表示输出前i