[kuangbin带你飞] 专题十三 基础计算几何 题解

这个专题除了最后两题其他题目都是几个月前写的了,所以就贴一下代码好了,就最后两题简单地说了一下思路



A - TOYS (POJ - 2318)

AC Code:

#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
using namespace std;    
const double pi = acos((double)(-1));
#define inf 0x3f3f3f3f
#define ll long long
#define eps 1e-8
const int maxn = 5010;
const int mod = 1e9 + 7;
int sgn(double x){                 //判断x是否为0
    if(fabs(x) < eps) return 0;
    else return x < 0?-1:1;
}
int dcmp(double x, double y){      //比较两个浮点数   
    if(fabs(x - y) < eps) return 0;
    else return x < y?-1:1;
}
struct Point{
    double x,y;
    Point(){}
    Point(double x,double y):x(x),y(y){}
    Point operator + (Point B){return Point(x + B.x,y + B.y);}
    Point operator - (Point B){return Point(x - B.x,y - B.y);}
    Point operator * (double k){return Point(x*k,y*k);}
    Point operator / (double k){return Point(x/k,y/k);}
    bool operator == (Point B){return sgn(x - B.x) == 0 && sgn(y - B.y) == 0;}
}P[maxn];
typedef Point Vector;   //用点的数据结构定义向量
struct Line{
    Point p1,p2;
    Line(){}
    Line(Point p1,Point p2):p1(p1),p2(p2){}
    Line(Point p,double angle){    //y = kx + b
        p1 = p;
        if(sgn(angle - pi/2) == 0){p2 = (p1 + Point(0,1));}
        else {p2 = (p1 + Point(1,tan(angle)));}
    }
    Line(double a,double b,double c){    //ax + by + c = 0
        if(sgn(a) == 0){
            p1 = Point(0, -c/b);
            p2 = Point(1, -c/b);
        }
        else if(sgn(b) == 0){
            p1 = Point(-c/a,0);
            p2 = Point(-c/a,1);
        }
        else{
            p1 = Point(0,-c/b);
            p2 = Point(1,(-c - a)/b);
        }
    }
}L[maxn];
typedef Line Segment;
double Dist(Point A,Point B){
    return sqrt((A.x - B.x)*(A.x - B.x) + (A.y - B.y)*(A.y - B.y));
}
double Dot(Vector A,Vector B){return A.x*B.x + A.y*B.y;}  //计算向量点积,>0锐角,<0钝角,=0直角 A·B = fabs(A)*fabs(B)*cos(angle)
double Len(Vector A){return sqrt(Dot(A,A));}             //计算向量长度
double Len2(Vector A){return Dot(A,A);}                  //向量长度的平方
double Angle(Vector A,Vector B){return acos(Dot(A,B)/Len(A)/Len(B));}   //计算两向量的夹角
double Cross(Vector A,Vector B){return A.x*B.y - A.y*B.x;}  //计算向量叉积,叉积有正负,A×B>0(B在A的逆时针方向),B×A<0   A×B = fabs(A)*fabs(B)*sin(angle)
double Area(Vector A,Vector B,Vector C){return Cross(B- A,C - A);} //以A为公共点的两向量构成的平行四边形面积
Vector Rotate(Vector A,double rad){          //计算一个点逆时针选择rad度后的点
    return Vector(A.x*cos(rad) - A.y*sin(rad), A.x*sin(rad) + A.y*cos(rad));
}
Vector Normal(Vector A){return Vector(-A.y/Len(A),A.x/Len(A));}   //求该向量的法向量
bool Parallel(Vector A,Vector B){return sgn(Cross(A,B)) == 0;}  //用叉积判断两向量是否平行或重合
int Point_line_relation(Point p, Line v){                       //点和线的位置关系
    int c = sgn(Cross(p - v.p1, v.p2 - v.p1));
    if(c < 0) return 1;         //p在v的左边(上面)
    if(c > 0) return 2;         //p在v的右边(下面)
    return 0;
}
bool Point_on_seg(Point p, Line v){  //0为不在线段上,1为在线段上
    return sgn(Cross(p - v.p1, v.p2 - v.p1)) == 0 && sgn(Dot(p - v.p1, p - v.p2)) <=0;
}
double Dis_point_line(Point p, Line v){     //点到直线的距离
    return fabs(Cross(p - v.p1, v.p2 - v.p1))/Dist(v.p1, v.p2);
}
Point Point_line_proj(Point p, Line v){        //点在直线上的投影
    double k = Dot(v.p2 - v.p1, p - v.p1)/Len2(v.p2 - v.p1);
    return v.p1 + (v.p2 - v.p1) * k;
}
Point Point_line_symmetry(Point p, Line v){       //点关于直线的对称点
    Point q = Point_line_proj(p, v);
    return Point(2 * q.x - p.x, 2 * q.y - p.y);
}
double Dis_point_seg(Point p, Segment v){           //点到线段的距离
    if(sgn(Dot(p - v.p1, v.p2 - v.p1)) < 0 || sgn(Dot(p - v.p2, v.p1 - v.p2)) < 0)
        return min(Dist(p, v.p1), Dist(p, v.p2));
    return Dis_point_line(p, v);
}
int Line_relation(Line v1, Line v2){         //两条直线的位置关系
    if(sgn(Cross(v1.p2 - v1.p1, v2.p2 - v2.p1)) == 0){
        if(Point_line_relation(v1.p1, v2) == 0)  return 1;         //重合
        else return 0;                                             //平行
    }
    return 2;                                                      //相交
}
Point Cross_point(Point a, Point b, Point c, Point d){           //求两条直线的交点,Line1:ab,Line2:cd,两直线不平行不共线
    double s1 = Cross(b - a, c - a);
    double s2 = Cross(b - a, d - a);
    return Point(c.x * s2 - d.x * s1, c.y * s2 - d.y * s1) / (s2 - s1);
}
bool Cross_segment(Point a, Point b, Point c, Point d){               //两线段是否相交
    double c1 = Cross(b - a, c - a), c2 = Cross(b - a, d - a);
    double d1 = Cross(d - c, a - c), d2 = Cross(d - c, b - c);
    return sgn(c1) * sgn(c2) < 0 && sgn(d1) * sgn(d2) < 0;            //1:相交,0:不相交
    // return sgn(c1) * sgn(c2) <= 0 && sgn(d1) * sgn(d2) <= 0;         存在端点重合 
}
int n, m, X1, X2, Y1, Y2, sum[maxn];
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    while(cin>>n){
        if(n == 0) break;
        cin>>m>>X1>>Y1>>X2>>Y2;
        L[0].p1.x = X1, L[0].p1.y = Y1;
        L[0].p2.x = X1, L[0].p2.y = Y1 - 1;
        for(int i = 1, u, l; i <= n; i++){
            cin>>u>>l;
            L[i].p1.x = u, L[i].p1.y = Y1;
            L[i].p2.x = l, L[i].p2.y = Y2;
        }
        L[n + 1].p1.x = X2, L[n + 1].p1.y = Y2;
        L[n + 1].p2.x = X2, L[n + 1].p2.y = Y2 - 1;
        // for(int i = 0; i <= n + 1; i++)  cout<<L[i].p1.x<<" "<<L[i].p1.y<<" "<<L[i].p2.x<<" "<<L[i].p2.y<<endl;
        memset(sum, 0, sizeof(sum));
        for(int i = 1, x, y; i <= m ; i++){
            cin>>x>>y;
            P[1].x = x, P[1].y = y;
            // cout<<P[1].x<<" "<<P[1].y<<endl;
            // for(int j = 0; j <= n; j++){
            //     if(Point_line_relation(P[1], L[j]) * Point_line_relation(P[1], L[j + 1]) == 2){
            //         sum[j]++;
            //         break;
            //     }
            // }
            int l = 0, r = n, mid = (l + r)/2;
            while(r - l >= 0){
                mid = (l + r)/2;
                if(Point_line_relation(P[1], L[mid]) * Point_line_relation(P[1], L[mid + 1]) == 4) r = mid - 1;
                else l = mid + 1;
            }
            sum[r]++;
        }
        for(int i = 0; i <= n; i++){
            cout<<i<<": "<<sum[i]<<endl;
        }
        cout<<endl;
    }
    return 0;
}

B - Toy Storage (POJ - 2398)

AC Code:

#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
using namespace std;    
const double pi = acos((double)(-1));
#define inf 0x3f3f3f3f
#define ll long long
#define eps 1e-8
const int maxn = 5010;
const int mod = 1e9 + 7;
int sgn(double x){                 //判断x是否为0
    if(fabs(x) < eps) return 0;
    else return x < 0?-1:1;
}
int dcmp(double x, double y){      //比较两个浮点数   
    if(fabs(x - y) < eps) return 0;
    else return x < y?-1:1;
}
struct Point{
    double x,y;
    Point(){}
    Point(double x,double y):x(x),y(y){}
    Point operator + (Point B){return Point(x + B.x,y + B.y);}
    Point operator - (Point B){return Point(x - B.x,y - B.y);}
    Point operator * (double k){return Point(x*k,y*k);}
    Point operator / (double k){return Point(x/k,y/k);}
    bool operator == (Point B){return sgn(x - B.x) == 0 && sgn(y - B.y) == 0;}
}P[maxn];
typedef Point Vector;   //用点的数据结构定义向量
struct Line{
    Point p1,p2;
    Line(){}
    Line(Point p1,Point p2):p1(p1),p2(p2){}
    Line(Point p,double angle){    //y = kx + b
        p1 = p;
        if(sgn(angle - pi/2) == 0){p2 = (p1 + Point(0,1));}
        else {p2 = (p1 + Point(1,tan(angle)));}
    }
    Line(double a,double b,double c){    //ax + by + c = 0
        if(sgn(a) == 0){
            p1 = Point(0, -c/b);
            p2 = Point(1, -c/b);
        }
        else if(sgn(b) == 0){
            p1 = Point(-c/a,0);
            p2 = Point(-c/a,1);
        }
        else{
            p1 = Point(0,-c/b);
            p2 = Point(1,(-c - a)/b);
        }
    }
}L[maxn];
bool cmp(const Line &v1, const Line &v2){
    if(v1.p1.x != v2.p1.x) return v1.p1.x < v2.p1.x;
    return v1.p1.y < v2.p1.y;
}
typedef Line Segment;
double Dist(Point A,Point B){
    return sqrt((A.x - B.x)*(A.x - B.x) + (A.y - B.y)*(A.y - B.y));
}
double Dot(Vector A,Vector B){return A.x*B.x + A.y*B.y;}  //计算向量点积,>0锐角,<0钝角,=0直角 A·B = fabs(A)*fabs(B)*cos(angle)
double Len(Vector A){return sqrt(Dot(A,A));}             //计算向量长度
double Len2(Vector A){return Dot(A,A);}                  //向量长度的平方
double Angle(Vector A,Vector B){return acos(Dot(A,B)/Len(A)/Len(B));}   //计算两向量的夹角
double Cross(Vector A,Vector B){return A.x*B.y - A.y*B.x;}  //计算向量叉积,叉积有正负,A×B>0(B在A的逆时针方向),B×A<0   A×B = fabs(A)*fabs(B)*sin(angle)
double Area(Vector A,Vector B,Vector C){return Cross(B- A,C - A);} //以A为公共点的两向量构成的平行四边形面积
Vector Rotate(Vector A,double rad){          //计算一个点逆时针选择rad度后的点
    return Vector(A.x*cos(rad) - A.y*sin(rad), A.x*sin(rad) + A.y*cos(rad));
}
Vector Normal(Vector A){return Vector(-A.y/Len(A),A.x/Len(A));}   //求该向量的法向量
bool Parallel(Vector A,Vector B){return sgn(Cross(A,B)) == 0;}  //用叉积判断两向量是否平行或重合
int Point_line_relation(Point p, Line v){                       //点和线的位置关系
    int c = sgn(Cross(p - v.p1, v.p2 - v.p1));
    if(c < 0) return 1;         //p在v的左边(上面)
    if(c > 0) return 2;         //p在v的右边(下面)
    return 0;
}
bool Point_on_seg(Point p, Line v){  //0为不在线段上,1为在线段上
    return sgn(Cross(p - v.p1, v.p2 - v.p1)) == 0 && sgn(Dot(p - v.p1, p - v.p2)) <=0;
}
double Dis_point_line(Point p, Line v){     //点到直线的距离
    return fabs(Cross(p - v.p1, v.p2 - v.p1))/Dist(v.p1, v.p2);
}
Point Point_line_proj(Point p, Line v){        //点在直线上的投影
    double k = Dot(v.p2 - v.p1, p - v.p1)/Len2(v.p2 - v.p1);
    return v.p1 + (v.p2 - v.p1) * k;
}
Point Point_line_symmetry(Point p, Line v){       //点关于直线的对称点
    Point q = Point_line_proj(p, v);
    return Point(2 * q.x - p.x, 2 * q.y - p.y);
}
double Dis_point_seg(Point p, Segment v){           //点到线段的距离
    if(sgn(Dot(p - v.p1, v.p2 - v.p1)) < 0 || sgn(Dot(p - v.p2, v.p1 - v.p2)) < 0)
        return min(Dist(p, v.p1), Dist(p, v.p2));
    return Dis_point_line(p, v);
}
int Line_relation(Line v1, Line v2){         //两条直线的位置关系
    if(sgn(Cross(v1.p2 - v1.p1, v2.p2 - v2.p1)) == 0){
        if(Point_line_relation(v1.p1, v2) == 0)  return 1;         //重合
        else return 0;                                             //平行
    }
    return 2;                                                      //相交
}
Point Cross_point(Point a, Point b, Point c, Point d){           //求两条直线的交点,Line1:ab,Line2:cd,两直线不平行不共线
    double s1 = Cross(b - a, c - a);
    double s2 = Cross(b - a, d - a);
    return Point(c.x * s2 - d.x * s1, c.y * s2 - d.y * s1) / (s2 - s1);
}
bool Cross_segment(Point a, Point b, Point c, Point d){               //两线段是否相交
    double c1 = Cross(b - a, c - a), c2 = Cross(b - a, d - a);
    double d1 = Cross(d - c, a - c), d2 = Cross(d - c, b - c);
    return sgn(c1) * sgn(c2) < 0 && sgn(d1) * sgn(d2) < 0;            //1:相交,0:不相交
    // return sgn(c1) * sgn(c2) <= 0 && sgn(d1) * sgn(d2) <= 0;         存在端点重合 
}
int n, m, X1, X2, Y1, Y2, sum[maxn], ans[maxn];
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    while(cin>>n){
        if(n == 0) break;
        cin>>m>>X1>>Y1>>X2>>Y2;
        L[0].p1.x = X1, L[0].p1.y = Y1;
        L[0].p2.x = X1, L[0].p2.y = Y1 - 1;
        for(int i = 1, u, l; i <= n; i++){
            cin>>u>>l;
            L[i].p1.x = u, L[i].p1.y = Y1;
            L[i].p2.x = l, L[i].p2.y = Y2;
        }
        L[n + 1].p1.x = X2, L[n + 1].p1.y = Y2;
        L[n + 1].p2.x = X2, L[n + 1].p2.y = Y2 - 1;
        sort(L,L + n + 2, cmp);
        // for(int i = 0; i <= n + 1; i++)  cout<<L[i].p1.x<<" "<<L[i].p1.y<<" "<<L[i].p2.x<<" "<<L[i].p2.y<<endl;
        memset(sum, 0, sizeof(sum));
        memset(ans, 0, sizeof(ans));
        for(int i = 1, x, y; i <= m ; i++){
            cin>>x>>y;
            P[1].x = x, P[1].y = y;
            // cout<<P[1].x<<" "<<P[1].y<<endl;
            // for(int j = 0; j <= n; j++){
            //     if(Point_line_relation(P[1], L[j]) * Point_line_relation(P[1], L[j + 1]) == 2){
            //         sum[j]++;
            //         break;
            //     }
            // }
            int l = 0, r = n, mid = (l + r)/2;
            while(r - l >= 0){
                mid = (l + r)/2;
                if(Point_line_relation(P[1], L[mid]) * Point_line_relation(P[1], L[mid + 1]) == 4) r = mid - 1;
                else l = mid + 1;
            }
            sum[r]++;
        }
        for(int i = 0; i <= n; i++){
            if(sum[i]) ans[sum[i]]++;
        }
        cout<<"Box"<<endl;
        for(int i = 1; i <= m; i++){
            if(ans[i]) cout<<i<<": "<<ans[i]<<endl;
        }
    }
    return 0;
}

C - Segments (POJ - 3304)

AC Code:

#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<iomanip>
using namespace std;    
const double pi = acos((double)(-1));
#define inf 0x3f3f3f3f
#define ll long long
#define eps 1e-8
const int maxn = 5010;
const int mod = 1e9 + 7;
int sgn(double x){                 //判断x是否为0
    if(fabs(x) < eps) return 0;
    else return x < 0?-1:1;
}
int dcmp(double x, double y){      //比较两个浮点数   
    if(fabs(x - y) < eps) return 0;
    else return x < y?-1:1;
}
struct Point{
    double x,y;
    Point(){}
    Point(double x,double y):x(x),y(y){}
    Point operator + (Point B){return Point(x + B.x,y + B.y);}
    Point operator - (Point B){return Point(x - B.x,y - B.y);}
    Point operator * (double k){return Point(x*k,y*k);}
    Point operator / (double k){return Point(x/k,y/k);}
    bool operator == (Point B){return sgn(x - B.x) == 0 && sgn(y - B.y) == 0;}
}P[maxn];
typedef Point Vector;   //用点的数据结构定义向量
struct Line{
    Point p1,p2;
    Line(){}
    Line(Point p1,Point p2):p1(p1),p2(p2){}
    Line(Point p,double angle){    //y = kx + b
        p1 = p;
        if(sgn(angle - pi/2) == 0){p2 = (p1 + Point(0,1));}
        else {p2 = (p1 + Point(1,tan(angle)));}
    }
    Line(double a,double b,double c){    //ax + by + c = 0
        if(sgn(a) == 0){
            p1 = Point(0, -c/b);
            p2 = Point(1, -c/b);
        }
        else if(sgn(b) == 0){
            p1 = Point(-c/a,0);
            p2 = Point(-c/a,1);
        }
        else{
            p1 = Point(0,-c/b);
            p2 = Point(1,(-c - a)/b);
        }
    }
}L[maxn];
bool cmp(const Line &v1, const Line &v2){
    if(v1.p1.x != v2.p1.x) return v1.p1.x < v2.p1.x;
    return v1.p1.y < v2.p1.y;
}
typedef Line Segment;
double Dist(Point A,Point B){
    return sqrt((A.x - B.x)*(A.x - B.x) + (A.y - B.y)*(A.y - B.y));
}
double Dot(Vector A,Vector B){return A.x*B.x + A.y*B.y;}  //计算向量点积,>0锐角,<0钝角,=0直角 A·B = fabs(A)*fabs(B)*cos(angle)
double Len(Vector A){return sqrt(Dot(A,A));}             //计算向量长度
double Len2(Vector A){return Dot(A,A);}                  //向量长度的平方
double Angle(Vector A,Vector B){return acos(Dot(A,B)/Len(A)/Len(B));}   //计算两向量的夹角
double Cross(Vector A,Vector B){return A.x*B.y - A.y*B.x;}  //计算向量叉积,叉积有正负,A×B>0(B在A的逆时针方向),B×A<0   A×B = fabs(A)*fabs(B)*sin(angle)
double Area(Vector A,Vector B,Vector C){return Cross(B- A,C - A);} //以A为公共点的两向量构成的平行四边形面积
Vector Rotate(Vector A,double rad){          //计算一个点逆时针选择rad度后的点
    return Vector(A.x*cos(rad) - A.y*sin(rad), A.x*sin(rad) + A.y*cos(rad));
}
Vector Normal(Vector A){return Vector(-A.y/Len(A),A.x/Len(A));}   //求该向量的法向量
bool Parallel(Vector A,Vector B){return sgn(Cross(A,B)) == 0;}  //用叉积判断两向量是否平行或重合
int Point_line_relation(Point p, Line v){                       //点和线的位置关系
    int c = sgn(Cross(p - v.p1, v.p2 - v.p1));
    if(c < 0) return 1;         //p在v的左边(上面)
    if(c > 0) return 2;         //p在v的右边(下面)
    return 0;
}
bool Point_on_seg(Point p, Line v){  //0为不在线段上,1为在线段上
    return sgn(Cross(p - v.p1, v.p2 - v.p1)) == 0 && sgn(Dot(p - v.p1, p - v.p2)) <=0;
}
double Dis_point_line(Point p, Line v){     //点到直线的距离
    return fabs(Cross(p - v.p1, v.p2 - v.p1))/Dist(v.p1, v.p2);
}
Point Point_line_proj(Point p, Line v){        //点在直线上的投影
    double k = Dot(v.p2 - v.p1, p - v.p1)/Len2(v.p2 - v.p1);
    return v.p1 + (v.p2 - v.p1) * k;
}
Point Point_line_symmetry(Point p, Line v){       //点关于直线的对称点
    Point q = Point_line_proj(p, v);
    return Point(2 * q.x - p.x, 2 * q.y - p.y);
}
double Dis_point_seg(Point p, Segment v){           //点到线段的距离
    if(sgn(Dot(p - v.p1, v.p2 - v.p1)) < 0 || sgn(Dot(p - v.p2, v.p1 - v.p2)) < 0)
        return min(Dist(p, v.p1), Dist(p, v.p2));
    return Dis_point_line(p, v);
}
int Line_relation(Line v1, Line v2){         //两条直线的位置关系
    if(sgn(Cross(v1.p2 - v1.p1, v2.p2 - v2.p1)) == 0){
        if(Point_line_relation(v1.p1, v2) == 0)  return 1;         //重合
        else return 0;                                             //平行
    }
    return 2;                                                      //相交
}
Point Cross_point(Point a, Point b, Point c, Point d){           //求两条直线的交点,Line1:ab,Line2:cd,两直线不平行不共线
    double s1 = Cross(b - a, c - a);
    double s2 = Cross(b - a, d - a);
    return Point(c.x * s2 - d.x * s1, c.y * s2 - d.y * s1) / (s2 - s1);
}
bool Cross_segment(Point a, Point b, Point c, Point d){               //两线段是否相交
    double c1 = Cross(b - a, c - a), c2 = Cross(b - a, d - a);
    double d1 = Cross(d - c, a - c), d2 = Cross(d - c, b - c);
    return sgn(c1) * sgn(c2) < 0 && sgn(d1) * sgn(d2) < 0;            //1:相交,0:不相交
    // return sgn(c1) * sgn(c2) <= 0 && sgn(d1) * sgn(d2) <= 0;         存在端点重合 
}
int t, n, f;
bool judge(Line v){
     for(int k = 1; k < 2 * n ; k = k + 2){
        if(Point_line_relation(P[k], v) * Point_line_relation(P[k + 1],v) == 1 || Point_line_relation(P[k],v) * Point_line_relation(P[k + 1], v) == 4)   return false;
     }
     return true;
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>t;
    while(t--){
        cin>>n;
        for(int i = 1; i <= 2 * n ; i ++){
            cin>>P[i].x>>P[i].y;
        }
        f = 0;
        for(int i = 1; i < 2 * n; i++){
            for(int j = i + 1 ; j <= 2 * n; j++){
                L[1].p1.x = P[i].x;
                L[1].p1.y = P[i].y;
                L[1].p2.x = P[j].x;
                L[1].p2.y = P[j].y;
                if(sgn(Dist(L[1].p1, L[1].p2)) == 0) continue;
                if(judge(L[1]))  f = 1;
                if(f) break;
            }
            if(f) break;
        }
        if(f) puts("Yes!");
        else puts("No!");
    }
    return 0;
}

D - Intersecting Lines (POJ 1269)

AC Code:

#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<iomanip>
using namespace std;    
const double pi = acos((double)(-1));
#define inf 0x3f3f3f3f
#define ll long long
#define eps 1e-8
const int maxn = 5010;
const int mod = 1e9 + 7;
int sgn(double x){                 //判断x是否为0
    if(fabs(x) < eps) return 0;
    else return x < 0?-1:1;
}
int dcmp(double x, double y){      //比较两个浮点数   
    if(fabs(x - y) < eps) return 0;
    else return x < y?-1:1;
}
struct Point{
    double x,y;
    Point(){}
    Point(double x,double y):x(x),y(y){}
    Point operator + (Point B){return Point(x + B.x,y + B.y);}
    Point operator - (Point B){return Point(x - B.x,y - B.y);}
    Point operator * (double k){return Point(x*k,y*k);}
    Point operator / (double k){return Point(x/k,y/k);}
    bool operator == (Point B){return sgn(x - B.x) == 0 && sgn(y - B.y) == 0;}
}P[maxn];
typedef Point Vector;   //用点的数据结构定义向量
struct Line{
    Point p1,p2;
    Line(){}
    Line(Point p1,Point p2):p1(p1),p2(p2){}
    Line(Point p,double angle){    //y = kx + b
        p1 = p;
        if(sgn(angle - pi/2) == 0){p2 = (p1 + Point(0,1));}
        else {p2 = (p1 + Point(1,tan(angle)));}
    }
    Line(double a,double b,double c){    //ax + by + c = 0
        if(sgn(a) == 0){
            p1 = Point(0, -c/b);
            p2 = Point(1, -c/b);
        }
        else if(sgn(b) == 0){
            p1 = Point(-c/a,0);
            p2 = Point(-c/a,1);
        }
        else{
            p1 = Point(0,-c/b);
            p2 = Point(1,(-c - a)/b);
        }
    }
}L[maxn];
bool cmp(const Line &v1, const Line &v2){
    if(v1.p1.x != v2.p1.x) return v1.p1.x < v2.p1.x;
    return v1.p1.y < v2.p1.y;
}
typedef Line Segment;
double Dist(Point A,Point B){
    return sqrt((A.x - B.x)*(A.x - B.x) + (A.y - B.y)*(A.y - B.y));
}
double Dot(Vector A,Vector B){return A.x*B.x + A.y*B.y;}  //计算向量点积,>0锐角,<0钝角,=0直角 A·B = fabs(A)*fabs(B)*cos(angle)
double Len(Vector A){return sqrt(Dot(A,A));}             //计算向量长度
double Len2(Vector A){return Dot(A,A);}                  //向量长度的平方
double Angle(Vector A,Vector B){return acos(Dot(A,B)/Len(A)/Len(B));}   //计算两向量的夹角
double Cross(Vector A,Vector B){return A.x*B.y - A.y*B.x;}  //计算向量叉积,叉积有正负,A×B>0(B在A的逆时针方向),B×A<0   A×B = fabs(A)*fabs(B)*sin(angle)
double Area(Vector A,Vector B,Vector C){return Cross(B- A,C - A);} //以A为公共点的两向量构成的平行四边形面积
Vector Rotate(Vector A,double rad){          //计算一个点逆时针选择rad度后的点
    return Vector(A.x*cos(rad) - A.y*sin(rad), A.x*sin(rad) + A.y*cos(rad));
}
Vector Normal(Vector A){return Vector(-A.y/Len(A),A.x/Len(A));}   //求该向量的法向量
bool Parallel(Vector A,Vector B){return sgn(Cross(A,B)) == 0;}  //用叉积判断两向量是否平行或重合
int Point_line_relation(Point p, Line v){                       //点和线的位置关系
    int c = sgn(Cross(p - v.p1, v.p2 - v.p1));
    if(c < 0) return 1;         //p在v的左边(上面)
    if(c > 0) return 2;         //p在v的右边(下面)
    return 0;
}
bool Point_on_seg(Point p, Line v){  //0为不在线段上,1为在线段上
    return sgn(Cross(p - v.p1, v.p2 - v.p1)) == 0 && sgn(Dot(p - v.p1, p - v.p2)) <=0;
}
double Dis_point_line(Point p, Line v){     //点到直线的距离
    return fabs(Cross(p - v.p1, v.p2 - v.p1))/Dist(v.p1, v.p2);
}
Point Point_line_proj(Point p, Line v){        //点在直线上的投影
    double k = Dot(v.p2 - v.p1, p - v.p1)/Len2(v.p2 - v.p1);
    return v.p1 + (v.p2 - v.p1) * k;
}
Point Point_line_symmetry(Point p, Line v){       //点关于直线的对称点
    Point q = Point_line_proj(p, v);
    return Point(2 * q.x - p.x, 2 * q.y - p.y);
}
double Dis_point_seg(Point p, Segment v){           //点到线段的距离
    if(sgn(Dot(p - v.p1, v.p2 - v.p1)) < 0 || sgn(Dot(p - v.p2, v.p1 - v.p2)) < 0)
        return min(Dist(p, v.p1), Dist(p, v.p2));
    return Dis_point_line(p, v);
}
int Line_relation(Line v1, Line v2){         //两条直线的位置关系
    if(sgn(Cross(v1.p2 - v1.p1, v2.p2 - v2.p1)) == 0){
        if(Point_line_relation(v1.p1, v2) == 0)  return 1;         //重合
        else return 0;                                             //平行
    }
    return 2;                                                      //相交
}
Point Cross_point(Point a, Point b, Point c, Point d){           //求两条直线的交点,Line1:ab,Line2:cd,两直线不平行不共线
    double s1 = Cross(b - a, c - a);
    double s2 = Cross(b - a, d - a);
    return Point(c.x * s2 - d.x * s1, c.y * s2 - d.y * s1) / (s2 - s1);
}
bool Cross_segment(Point a, Point b, Point c, Point d){               //两线段是否相交
    double c1 = Cross(b - a, c - a), c2 = Cross(b - a, d - a);
    double d1 = Cross(d - c, a - c), d2 = Cross(d - c, b - c);
    return sgn(c1) * sgn(c2) < 0 && sgn(d1) * sgn(d2) < 0;            //1:相交,0:不相交
    // return sgn(c1) * sgn(c2) <= 0 && sgn(d1) * sgn(d2) <= 0;         存在端点重合 
}
int n;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>n;
    cout<<"INTERSECTING LINES OUTPUT"<<endl;
    while(n--){
        cin>>L[1].p1.x>>L[1].p1.y>>L[1].p2.x>>L[1].p2.y;
        cin>>L[2].p1.x>>L[2].p1.y>>L[2].p2.x>>L[2].p2.y;
        if(Line_relation(L[1], L[2]) == 1) cout<<"LINE"<<endl;
        else if(Line_relation(L[1], L[2]) == 0) cout<<"NONE"<<endl;
        else{
            P[1] = Cross_point(L[1].p1, L[1].p2, L[2].p1, L[2].p2);
            cout<<"POINT ";
            cout<<fixed<<setprecision(2)<<P[1].x<<" "<<P[1].y<<endl;
        }
    }
    cout<<"END OF OUTPUT"<<endl;
    return 0;
}

E - The Doors (POJ - 1556)

AC Code:

#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<iomanip>
using namespace std;    
const double pi = acos((double)(-1));
#define inf 0x3f3f3f3f
#define ll long long
#define eps 1e-8
const int maxn = 110;
const int mod = 1e9 + 7;
int sgn(double x){
    if(fabs(x) < eps) return 0;
    else return x < 0?-1:1;
}
struct Point{
    double x,y;
    Point(){}
    Point(double x,double y):x(x),y(y){}
    Point operator + (Point B){return Point(x + B.x,y + B.y);}
    Point operator - (Point B){return Point(x - B.x,y - B.y);}
    Point operator * (double k){return Point(x*k,y*k);}
    Point operator / (double k){return Point(x/k,y/k);}
    bool operator == (Point B){return sgn(x - B.x) == 0 && sgn(y - B.y) == 0;}
}P[maxn];
typedef Point Vector;
struct Line{
    Point p1,p2;
    Line(){}
    Line(Point p1,Point p2):p1(p1),p2(p2){}
    Line(Point p,double angle){    //y = kx + b
        p1 = p;
        if(sgn(angle - pi/2) == 0){p2 = (p1 + Point(0,1));}
        else {p2 = (p1 + Point(1,tan(angle)));}
    }
    Line(double a,double b,double c){    //ax + by + c = 0
        if(sgn(a) == 0){
            p1 = Point(0, -c/b);
            p2 = Point(1, -c/b);
        }
        else if(sgn(b) == 0){
            p1 = Point(-c/a,0);
            p2 = Point(-c/a,1);
        }
        else{
            p1 = Point(0,-c/b);
            p2 = Point(1,(-c - a)/b);
        }
    }
}L[maxn];
typedef Line Segment;
double Dist(Point A,Point B){
    return sqrt((A.x - B.x)*(A.x - B.x) + (A.y - B.y)*(A.y - B.y));
}
double Cross(Vector A,Vector B){return A.x*B.y - A.y*B.x;}
bool Cross_segment(Point a, Point b, Point c, Point d){         
    double c1 = Cross(b - a, c - a), c2 = Cross(b - a, d - a);
    double d1 = Cross(d - c, a - c), d2 = Cross(d - c, b - c);
    return sgn(c1) * sgn(c2) < 0 && sgn(d1) * sgn(d2) < 0;           
}
int n;
double x, y;
bool judge(Line v){
    for(int k = 1; k <= 6 * n; k+=2){
        if(Cross_segment(L[1].p1, L[1].p2, P[k], P[k + 1]) == 1) return false;
    }
    return true;
}
double d[maxn];
int vis[maxn];
struct node{
	int to;
    double w;
    node(int to_,double w_){
		to = to_,w = w_;
	}
};
vector<node>v[maxn];
void Dij(){
	 d[0] = 0;
	 while(1){
	 	double min1=999999.0 ;
        int z = -1;
	 	for(int i = 0;i < 6 * n + 1; i++){
	 		if(d[i] < min1 && !vis[i]){
	 			min1 = d[i];
	 			z = i;
			 }
		 }
		 if(z == -1)  break;
		 vis[z] = 1;
		 for(int i = 0;i < v[z].size(); i++){
		 	int vv = v[z][i].to;
            double dis = v[z][i].w;
            if(d[vv] > dis + d[z]) d[vv] = dis + d[z];
		 }
	 }
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    while(cin>>n){
        if(n == -1) break;
        for(int i = 0;i <= 6 * n + 1;i++){
		    v[i].clear();
		    vis[i]=0;
		    d[i]=99999.0;
	    }
        P[0].x = 0;
        P[0].y = 5;
        for(int i = 1; i <= n; i++){
            cin>>x;
            P[(i - 1) * 6 + 1].x = x;
            P[(i - 1) * 6 + 1].y = 0;
            for(int j = 2; j <= 5; j++){
                cin>>y;
                P[(i - 1) * 6 + j].x = x;
                P[(i - 1) * 6 + j].y = y;
            }
            P[(i - 1) * 6 + 6].x = x;
            P[(i - 1) * 6 + 6].y = 10;
        }
        P[6 * n + 1].x = 10;
        P[6 * n + 1].y = 5;   //true
        for(int i = 0; i < 6 * n + 1; i++){
            if((i % 6 == 1 || i % 6 == 0) && i != 0) continue;
            for(int j = i + 1; j <= 6 * n + 1; j++){
                if((j % 6 == 1 || j % 6 == 0) && j != 6 * n + 1) continue;
                L[1].p1.x = P[i].x;
                L[1].p1.y = P[i].y;
                L[1].p2.x = P[j].x;
                L[1].p2.y = P[j].y;
                if(judge(L[1])){
                    double dist = Dist(P[i] ,P[j]);
                    v[i].push_back(node(j, dist));
                }
            }
        }
        Dij();
        cout<<fixed<<setprecision(2)<<d[6 * n + 1]<<endl;
    }
    return 0;
}

F - Pick-up sticks (POJ - 2653)

AC Code:

#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<iomanip>
using namespace std;    
const double pi = acos((double)(-1));
#define inf 0x3f3f3f3f
#define ll long long
#define eps 1e-8
const int maxn = 100010;
const int mod = 1e9 + 7;
int sgn(double x){                 //判断x是否为0
    if(fabs(x) < eps) return 0;
    else return x < 0?-1:1;
}
int dcmp(double x, double y){      //比较两个浮点数   
    if(fabs(x - y) < eps) return 0;
    else return x < y?-1:1;
}
struct Point{
    double x,y;
    Point(){}
    Point(double x,double y):x(x),y(y){}
    Point operator + (Point B){return Point(x + B.x,y + B.y);}
    Point operator - (Point B){return Point(x - B.x,y - B.y);}
    Point operator * (double k){return Point(x*k,y*k);}
    Point operator / (double k){return Point(x/k,y/k);}
    bool operator == (Point B){return sgn(x - B.x) == 0 && sgn(y - B.y) == 0;}
}P[maxn];
typedef Point Vector;   //用点的数据结构定义向量
struct Line{
    Point p1,p2;
    Line(){}
    Line(Point p1,Point p2):p1(p1),p2(p2){}
    Line(Point p,double angle){    //y = kx + b
        p1 = p;
        if(sgn(angle - pi/2) == 0){p2 = (p1 + Point(0,1));}
        else {p2 = (p1 + Point(1,tan(angle)));}
    }
    Line(double a,double b,double c){    //ax + by + c = 0
        if(sgn(a) == 0){
            p1 = Point(0, -c/b);
            p2 = Point(1, -c/b);
        }
        else if(sgn(b) == 0){
            p1 = Point(-c/a,0);
            p2 = Point(-c/a,1);
        }
        else{
            p1 = Point(0,-c/b);
            p2 = Point(1,(-c - a)/b);
        }
    }
}L[maxn];
bool cmp(const Line &v1, const Line &v2){
    if(v1.p1.x != v2.p1.x) return v1.p1.x < v2.p1.x;
    return v1.p1.y < v2.p1.y;
}
typedef Line Segment;
double Dist(Point A,Point B){
    return sqrt((A.x - B.x)*(A.x - B.x) + (A.y - B.y)*(A.y - B.y));
}
double Dot(Vector A,Vector B){return A.x*B.x + A.y*B.y;}  //计算向量点积,>0锐角,<0钝角,=0直角 A·B = fabs(A)*fabs(B)*cos(angle)
double Len(Vector A){return sqrt(Dot(A,A));}             //计算向量长度
double Len2(Vector A){return Dot(A,A);}                  //向量长度的平方
double Angle(Vector A,Vector B){return acos(Dot(A,B)/Len(A)/Len(B));}   //计算两向量的夹角
double Cross(Vector A,Vector B){return A.x*B.y - A.y*B.x;}  //计算向量叉积,叉积有正负,A×B>0(B在A的逆时针方向),B×A<0   A×B = fabs(A)*fabs(B)*sin(angle)
double Area(Vector A,Vector B,Vector C){return Cross(B- A,C - A);} //以A为公共点的两向量构成的平行四边形面积
Vector Rotate(Vector A,double rad){          //计算一个点逆时针选择rad度后的点
    return Vector(A.x*cos(rad) - A.y*sin(rad), A.x*sin(rad) + A.y*cos(rad));
}
Vector Normal(Vector A){return Vector(-A.y/Len(A),A.x/Len(A));}   //求该向量的法向量
bool Parallel(Vector A,Vector B){return sgn(Cross(A,B)) == 0;}  //用叉积判断两向量是否平行或重合
int Point_line_relation(Point p, Line v){                       //点和线的位置关系
    int c = sgn(Cross(p - v.p1, v.p2 - v.p1));
    if(c < 0) return 1;         //p在v的左边(上面)
    if(c > 0) return 2;         //p在v的右边(下面)
    return 0;
}
bool Point_on_seg(Point p, Line v){  //0为不在线段上,1为在线段上
    return sgn(Cross(p - v.p1, v.p2 - v.p1)) == 0 && sgn(Dot(p - v.p1, p - v.p2)) <=0;
}
double Dis_point_line(Point p, Line v){     //点到直线的距离
    return fabs(Cross(p - v.p1, v.p2 - v.p1))/Dist(v.p1, v.p2);
}
Point Point_line_proj(Point p, Line v){        //点在直线上的投影
    double k = Dot(v.p2 - v.p1, p - v.p1)/Len2(v.p2 - v.p1);
    return v.p1 + (v.p2 - v.p1) * k;
}
Point Point_line_symmetry(Point p, Line v){       //点关于直线的对称点
    Point q = Point_line_proj(p, v);
    return Point(2 * q.x - p.x, 2 * q.y - p.y);
}
double Dis_point_seg(Point p, Segment v){           //点到线段的距离
    if(sgn(Dot(p - v.p1, v.p2 - v.p1)) < 0 || sgn(Dot(p - v.p2, v.p1 - v.p2)) < 0)
        return min(Dist(p, v.p1), Dist(p, v.p2));
    return Dis_point_line(p, v);
}
int Line_relation(Line v1, Line v2){         //两条直线的位置关系
    if(sgn(Cross(v1.p2 - v1.p1, v2.p2 - v2.p1)) == 0){
        if(Point_line_relation(v1.p1, v2) == 0)  return 1;         //重合
        else return 0;                                             //平行
    }
    return 2;                                                      //相交
}
Point Cross_point(Point a, Point b, Point c, Point d){           //求两条直线的交点,Line1:ab,Line2:cd,两直线不平行不共线
    double s1 = Cross(b - a, c - a);
    double s2 = Cross(b - a, d - a);
    return Point(c.x * s2 - d.x * s1, c.y * s2 - d.y * s1) / (s2 - s1);
}
bool Cross_segment(Point a, Point b, Point c, Point d){               //两线段是否相交
    double c1 = Cross(b - a, c - a), c2 = Cross(b - a, d - a);
    double d1 = Cross(d - c, a - c), d2 = Cross(d - c, b - c);
    return sgn(c1) * sgn(c2) < 0 && sgn(d1) * sgn(d2) < 0;            //1:相交,0:不相交,端点重合不相交
    // return sgn(c1) * sgn(c2) <= 0 && sgn(d1) * sgn(d2) <= 0;            //端点重合算相交
}
int n, a[maxn];
double X1, X2, Y1, Y2;
bool judge(Line v1, Line v2){
    if(Cross_segment(v1.p1, v1.p2, v2.p1, v2.p2)) return false;
    return true;
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    while(cin>>n){
        if(n == 0) break;
        for(int i = 1; i <= n; i++){
            cin>>X1>>Y1>>X2>>Y2;
            L[i].p1.x = X1;
            L[i].p1.y = Y1;
            L[i].p2.x = X2;
            L[i].p2.y = Y2;
        }
        memset(a, 0, sizeof(a));
        int cnt = 0;
        for(int i = 1; i < n; i++){
            int f = 1;
            for(int j = i + 1; j <= n; j++){
                if(!judge(L[i], L[j])){
                    f = 0;
                    break;
                }
            }
            if(f){
                cnt++;
                a[cnt] = i;
            }
        }
        cnt++;
        a[cnt] = n;
        cout<<"Top sticks:";
        for(int i = 1; i < cnt; i++) cout<<" "<<a[i]<<",";
        cout<<" "<<a[cnt]<<"."<<endl;
    }
    return 0;
}

G - Treasure Hunt (POJ - 1066)

AC Code:

#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<iomanip>
using namespace std;    
const double pi = acos((double)(-1));
#define inf 0x3f3f3f3f
#define ll long long
#define eps 1e-8
const int maxn = 110;
const int mod = 1e9 + 7;
int sgn(double x){                 //判断x是否为0
    if(fabs(x) < eps) return 0;
    else return x < 0?-1:1;
}
int dcmp(double x, double y){      //比较两个浮点数   
    if(fabs(x - y) < eps) return 0;
    else return x < y?-1:1;
}
struct Point{
    double x,y;
    Point(){}
    Point(double x,double y):x(x),y(y){}
    Point operator + (Point B){return Point(x + B.x,y + B.y);}
    Point operator - (Point B){return Point(x - B.x,y - B.y);}
    Point operator * (double k){return Point(x*k,y*k);}
    Point operator / (double k){return Point(x/k,y/k);}
    bool operator == (Point B){return sgn(x - B.x) == 0 && sgn(y - B.y) == 0;}
}P[maxn];
typedef Point Vector;   //用点的数据结构定义向量
struct Line{
    Point p1,p2;
    Line(){}
    Line(Point p1,Point p2):p1(p1),p2(p2){}
    Line(Point p,double angle){    //y = kx + b
        p1 = p;
        if(sgn(angle - pi/2) == 0){p2 = (p1 + Point(0,1));}
        else {p2 = (p1 + Point(1,tan(angle)));}
    }
    Line(double a,double b,double c){    //ax + by + c = 0
        if(sgn(a) == 0){
            p1 = Point(0, -c/b);
            p2 = Point(1, -c/b);
        }
        else if(sgn(b) == 0){
            p1 = Point(-c/a,0);
            p2 = Point(-c/a,1);
        }
        else{
            p1 = Point(0,-c/b);
            p2 = Point(1,(-c - a)/b);
        }
    }
}L[maxn];
bool cmp(const Line &v1, const Line &v2){
    if(v1.p1.x != v2.p1.x) return v1.p1.x < v2.p1.x;
    return v1.p1.y < v2.p1.y;
}
typedef Line Segment;
double Dist(Point A,Point B){
    return sqrt((A.x - B.x)*(A.x - B.x) + (A.y - B.y)*(A.y - B.y));
}
double Dot(Vector A,Vector B){return A.x*B.x + A.y*B.y;}  //计算向量点积,>0锐角,<0钝角,=0直角 A·B = fabs(A)*fabs(B)*cos(angle)
double Len(Vector A){return sqrt(Dot(A,A));}             //计算向量长度
double Len2(Vector A){return Dot(A,A);}                  //向量长度的平方
double Angle(Vector A,Vector B){return acos(Dot(A,B)/Len(A)/Len(B));}   //计算两向量的夹角
double Cross(Vector A,Vector B){return A.x*B.y - A.y*B.x;}  //计算向量叉积,叉积有正负,A×B>0(B在A的逆时针方向),B×A<0   A×B = fabs(A)*fabs(B)*sin(angle)
double Area(Vector A,Vector B,Vector C){return Cross(B- A,C - A);} //以A为公共点的两向量构成的平行四边形面积
Vector Rotate(Vector A,double rad){          //计算一个点逆时针选择rad度后的点
    return Vector(A.x*cos(rad) - A.y*sin(rad), A.x*sin(rad) + A.y*cos(rad));
}
Vector Normal(Vector A){return Vector(-A.y/Len(A),A.x/Len(A));}   //求该向量的法向量
bool Parallel(Vector A,Vector B){return sgn(Cross(A,B)) == 0;}  //用叉积判断两向量是否平行或重合
int Point_line_relation(Point p, Line v){                       //点和线的位置关系
    int c = sgn(Cross(p - v.p1, v.p2 - v.p1));
    if(c < 0) return 1;         //p在v的左边(上面)
    if(c > 0) return 2;         //p在v的右边(下面)
    return 0;
}
bool Point_on_seg(Point p, Line v){  //0为不在线段上,1为在线段上
    return sgn(Cross(p - v.p1, v.p2 - v.p1)) == 0 && sgn(Dot(p - v.p1, p - v.p2)) <=0;
}
double Dis_point_line(Point p, Line v){     //点到直线的距离
    return fabs(Cross(p - v.p1, v.p2 - v.p1))/Dist(v.p1, v.p2);
}
Point Point_line_proj(Point p, Line v){        //点在直线上的投影
    double k = Dot(v.p2 - v.p1, p - v.p1)/Len2(v.p2 - v.p1);
    return v.p1 + (v.p2 - v.p1) * k;
}
Point Point_line_symmetry(Point p, Line v){       //点关于直线的对称点
    Point q = Point_line_proj(p, v);
    return Point(2 * q.x - p.x, 2 * q.y - p.y);
}
double Dis_point_seg(Point p, Segment v){           //点到线段的距离
    if(sgn(Dot(p - v.p1, v.p2 - v.p1)) < 0 || sgn(Dot(p - v.p2, v.p1 - v.p2)) < 0)
        return min(Dist(p, v.p1), Dist(p, v.p2));
    return Dis_point_line(p, v);
}
int Line_relation(Line v1, Line v2){         //两条直线的位置关系
    if(sgn(Cross(v1.p2 - v1.p1, v2.p2 - v2.p1)) == 0){
        if(Point_line_relation(v1.p1, v2) == 0)  return 1;         //重合
        else return 0;                                             //平行
    }
    return 2;                                                      //相交
}
Point Cross_point(Point a, Point b, Point c, Point d){           //求两条直线的交点,Line1:ab,Line2:cd,两直线不平行不共线
    double s1 = Cross(b - a, c - a);
    double s2 = Cross(b - a, d - a);
    return Point(c.x * s2 - d.x * s1, c.y * s2 - d.y * s1) / (s2 - s1);
}
bool Cross_segment(Point a, Point b, Point c, Point d){               //两线段是否相交
    double c1 = Cross(b - a, c - a), c2 = Cross(b - a, d - a);
    double d1 = Cross(d - c, a - c), d2 = Cross(d - c, b - c);
    return sgn(c1) * sgn(c2) < 0 && sgn(d1) * sgn(d2) < 0;            //1:相交,0:不相交,端点重合不相交
    // return sgn(c1) * sgn(c2) <= 0 && sgn(d1) * sgn(d2) <= 0;            //端点重合算相交
}
int n;
double X1, X2, Y1, Y2;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>n;
    for(int i = 1; i <= 2 * n; i = i + 2){
        cin>>X1>>Y1>>X2>>Y2;
        P[i].x = X1;
        P[i].y = Y1;
        P[i + 1].x = X2;
        P[i + 1].y = Y2;
    }
    cin>>P[0].x>>P[0].y;
    int minn = inf, ans = 0;
    for(int i = 1; i <= 2 * n; i++){
        ans = 0;
        for(int j = 1; j <= 2 * n; j = j + 2){
            if(Cross_segment(P[0], P[i], P[j], P[j + 1]))  ans++;
        }
        minn = min(ans, minn);
    }
    if(n == 0) minn = 0;
    cout<<"Number of doors = "<<minn + 1<<endl;
    return 0;
}

H - Intersection (POJ - 1410)

AC Code:

#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<iomanip>
using namespace std;    
const double pi = acos((double)(-1));
#define inf 0x3f3f3f3f
#define ll long long
#define eps 1e-8
const int maxn = 110;
const int mod = 1e9 + 7;
int sgn(double x){                 //判断x是否为0
    if(fabs(x) < eps) return 0;
    else return x < 0?-1:1;
}
int dcmp(double x, double y){      //比较两个浮点数   
    if(fabs(x - y) < eps) return 0;
    else return x < y?-1:1;
}
struct Point{
    double x,y;
    Point(){}
    Point(double x,double y):x(x),y(y){}
    Point operator + (Point B){return Point(x + B.x,y + B.y);}
    Point operator - (Point B){return Point(x - B.x,y - B.y);}
    Point operator * (double k){return Point(x*k,y*k);}
    Point operator / (double k){return Point(x/k,y/k);}
    bool operator == (Point B){return sgn(x - B.x) == 0 && sgn(y - B.y) == 0;}
}P[maxn];
typedef Point Vector;   //用点的数据结构定义向量
struct Line{
    Point p1,p2;
    Line(){}
    Line(Point p1,Point p2):p1(p1),p2(p2){}
    Line(Point p,double angle){    //y = kx + b
        p1 = p;
        if(sgn(angle - pi/2) == 0){p2 = (p1 + Point(0,1));}
        else {p2 = (p1 + Point(1,tan(angle)));}
    }
    Line(double a,double b,double c){    //ax + by + c = 0
        if(sgn(a) == 0){
            p1 = Point(0, -c/b);
            p2 = Point(1, -c/b);
        }
        else if(sgn(b) == 0){
            p1 = Point(-c/a,0);
            p2 = Point(-c/a,1);
        }
        else{
            p1 = Point(0,-c/b);
            p2 = Point(1,(-c - a)/b);
        }
    }
}L[maxn];
bool cmp(const Line &v1, const Line &v2){
    if(v1.p1.x != v2.p1.x) return v1.p1.x < v2.p1.x;
    return v1.p1.y < v2.p1.y;
}
typedef Line Segment;
double Dist(Point A,Point B){
    return sqrt((A.x - B.x)*(A.x - B.x) + (A.y - B.y)*(A.y - B.y));
}
double Dot(Vector A,Vector B){return A.x*B.x + A.y*B.y;}  //计算向量点积,>0锐角,<0钝角,=0直角 A·B = fabs(A)*fabs(B)*cos(angle)
double Len(Vector A){return sqrt(Dot(A,A));}             //计算向量长度
double Len2(Vector A){return Dot(A,A);}                  //向量长度的平方
double Angle(Vector A,Vector B){return acos(Dot(A,B)/Len(A)/Len(B));}   //计算两向量的夹角
double Cross(Vector A,Vector B){return A.x*B.y - A.y*B.x;}  //计算向量叉积,叉积有正负,A×B>0(B在A的逆时针方向),B×A<0   A×B = fabs(A)*fabs(B)*sin(angle)
double Area(Vector A,Vector B,Vector C){return Cross(B- A,C - A);} //以A为公共点的两向量构成的平行四边形面积
Vector Rotate(Vector A,double rad){          //计算一个点逆时针选择rad度后的点
    return Vector(A.x*cos(rad) - A.y*sin(rad), A.x*sin(rad) + A.y*cos(rad));
}
Vector Normal(Vector A){return Vector(-A.y/Len(A),A.x/Len(A));}   //求该向量的法向量
bool Parallel(Vector A,Vector B){return sgn(Cross(A,B)) == 0;}  //用叉积判断两向量是否平行或重合
int Point_line_relation(Point p, Line v){                       //点和线的位置关系
    int c = sgn(Cross(p - v.p1, v.p2 - v.p1));
    if(c < 0) return 1;         //p在v的左边(上面)
    if(c > 0) return 2;         //p在v的右边(下面)
    return 0;
}
bool Point_on_seg(Point p, Line v){  //0为不在线段上,1为在线段上
    return sgn(Cross(p - v.p1, v.p2 - v.p1)) == 0 && sgn(Dot(p - v.p1, p - v.p2)) <=0;
}
double Dis_point_line(Point p, Line v){     //点到直线的距离
    return fabs(Cross(p - v.p1, v.p2 - v.p1))/Dist(v.p1, v.p2);
}
Point Point_line_proj(Point p, Line v){        //点在直线上的投影
    double k = Dot(v.p2 - v.p1, p - v.p1)/Len2(v.p2 - v.p1);
    return v.p1 + (v.p2 - v.p1) * k;
}
Point Point_line_symmetry(Point p, Line v){       //点关于直线的对称点
    Point q = Point_line_proj(p, v);
    return Point(2 * q.x - p.x, 2 * q.y - p.y);
}
double Dis_point_seg(Point p, Segment v){           //点到线段的距离
    if(sgn(Dot(p - v.p1, v.p2 - v.p1)) < 0 || sgn(Dot(p - v.p2, v.p1 - v.p2)) < 0)
        return min(Dist(p, v.p1), Dist(p, v.p2));
    return Dis_point_line(p, v);
}
int Line_relation(Line v1, Line v2){         //两条直线的位置关系
    if(sgn(Cross(v1.p2 - v1.p1, v2.p2 - v2.p1)) == 0){
        if(Point_line_relation(v1.p1, v2) == 0)  return 1;         //重合
        else return 0;                                             //平行
    }
    return 2;                                                      //相交
}
Point Cross_point(Point a, Point b, Point c, Point d){           //求两条直线的交点,Line1:ab,Line2:cd,两直线不平行不共线
    double s1 = Cross(b - a, c - a);
    double s2 = Cross(b - a, d - a);
    return Point(c.x * s2 - d.x * s1, c.y * s2 - d.y * s1) / (s2 - s1);
}
bool Cross_segment(Point a, Point b, Point c, Point d){               //两线段是否规范相交 即如果一条线段的一个端点恰在另一条线段上则不视为相交;如果两条线段部分重合,也不视为相交。
    double c1 = Cross(b - a, c - a), c2 = Cross(b - a, d - a);
    double d1 = Cross(d - c, a - c), d2 = Cross(d - c, b - c);
    return sgn(c1) * sgn(c2) < 0 && sgn(d1) * sgn(d2) < 0;            //1:相交,0:不相交,端点重合不相交
}
bool Cross_segment1(Point a, Point b, Point c, Point d){    //两线段是否非规范相交
    return 
    max(a.x, b.x) >= min(c.x, d.x)&&
    max(c.x, d.x) >= min(a.x, b.x)&&
    max(a.y, b.y) >= min(c.y, d.y)&&
    max(c.y, d.y) >= min(a.y, b.y)&&
    sgn(Cross(b - a, c - a)) * sgn(Cross(b - a, d - a)) <= 0&&
    sgn(Cross(d - c, a - c)) * sgn(Cross(d - c, b - c)) <= 0;
}
int n;
double X1, X2, Y1, Y2, topx, topy, botx, boty, X3, X4, Y3, Y4;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>n;
    while(n--){
        cin>>X1>>Y1>>X2>>Y2>>X3>>Y3>>X4>>Y4;
        topx = max(X3, X4);
        botx = min(X3, X4);
        topy = max(Y3, Y4);
        boty = min(Y3, Y4);
        P[1].x = X1;
        P[1].y = Y1;
        P[2].x = X2;
        P[2].y = Y2;
        P[3].x = topx;
        P[3].y = topy;
        P[4].x = topx;
        P[4].y = boty;
        P[5].x = botx;
        P[5].y = boty;
        P[6].x = botx;
        P[6].y = topy;
        int f = 0;
        if(Cross_segment1(P[1], P[2], P[3], P[4])) f = 1;
        if(Cross_segment1(P[1], P[2], P[3], P[6])) f = 1;
        if(Cross_segment1(P[1], P[2], P[5], P[4])) f = 1;
        if(Cross_segment1(P[1], P[2], P[5], P[6])) f = 1;
        if(max(X1, X2) < topx && max(Y1, Y2) < topy && min(X1, X2) > botx && min(Y1, Y2) > boty) f = 1;
        if(f) cout<<"T"<<endl;
        else cout<<"F"<<endl;
    }
    return 0;
}

I - Space Ant (POJ - 1696)

AC Code:

#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<iomanip>
using namespace std;    
const double pi = acos((double)(-1));
#define inf 0x3f3f3f3f
#define ll long long
#define eps 1e-8
const int maxn = 60;
const int mod = 1e9 + 7;
int sgn(double x){                 //判断x是否为0
    if(fabs(x) < eps) return 0;
    else return x < 0?-1:1;
}
int dcmp(double x, double y){      //比较两个浮点数   
    if(fabs(x - y) < eps) return 0;
    else return x < y?-1:1;
}
struct Point{
    double x,y;
    Point(){}
    Point(double x,double y):x(x),y(y){}
    Point operator + (Point B){return Point(x + B.x,y + B.y);}
    Point operator - (Point B){return Point(x - B.x,y - B.y);}
    Point operator * (double k){return Point(x*k,y*k);}
    Point operator / (double k){return Point(x/k,y/k);}
    bool operator == (Point B){return sgn(x - B.x) == 0 && sgn(y - B.y) == 0;}
}P[maxn];
typedef Point Vector;   //用点的数据结构定义向量
struct Line{
    Point p1,p2;
    Line(){}
    Line(Point p1,Point p2):p1(p1),p2(p2){}
    Line(Point p,double angle){    //y = kx + b
        p1 = p;
        if(sgn(angle - pi/2) == 0){p2 = (p1 + Point(0,1));}
        else {p2 = (p1 + Point(1,tan(angle)));}
    }
    Line(double a,double b,double c){    //ax + by + c = 0
        if(sgn(a) == 0){
            p1 = Point(0, -c/b);
            p2 = Point(1, -c/b);
        }
        else if(sgn(b) == 0){
            p1 = Point(-c/a,0);
            p2 = Point(-c/a,1);
        }
        else{
            p1 = Point(0,-c/b);
            p2 = Point(1,(-c - a)/b);
        }
    }
}L[maxn];
bool cmp(const Line &v1, const Line &v2){
    if(v1.p1.x != v2.p1.x) return v1.p1.x < v2.p1.x;
    return v1.p1.y < v2.p1.y;
}
typedef Line Segment;
double Dist(Point A,Point B){
    return sqrt((A.x - B.x)*(A.x - B.x) + (A.y - B.y)*(A.y - B.y));
}
double Dot(Vector A,Vector B){return A.x*B.x + A.y*B.y;}  //计算向量点积,>0锐角,<0钝角,=0直角 A·B = fabs(A)*fabs(B)*cos(angle)
double Len(Vector A){return sqrt(Dot(A,A));}             //计算向量长度
double Len2(Vector A){return Dot(A,A);}                  //向量长度的平方
double Angle(Vector A,Vector B){return acos(Dot(A,B)/Len(A)/Len(B));}   //计算两向量的夹角
double Cross(Vector A,Vector B){return A.x*B.y - A.y*B.x;}  //计算向量叉积,叉积有正负,A×B>0(B在A的逆时针方向),B×A<0   A×B = fabs(A)*fabs(B)*sin(angle)
double Area(Vector A,Vector B,Vector C){return Cross(B- A,C - A);} //以A为公共点的两向量构成的平行四边形面积
Vector Rotate(Vector A,double rad){          //计算一个点逆时针选择rad度后的点
    return Vector(A.x*cos(rad) - A.y*sin(rad), A.x*sin(rad) + A.y*cos(rad));
}
Vector Normal(Vector A){return Vector(-A.y/Len(A),A.x/Len(A));}   //求该向量的法向量
bool Parallel(Vector A,Vector B){return sgn(Cross(A,B)) == 0;}  //用叉积判断两向量是否平行或重合
int Point_line_relation(Point p, Line v){                       //点和线的位置关系
    int c = sgn(Cross(p - v.p1, v.p2 - v.p1));
    if(c < 0) return 1;         //p在v的左边(上面)
    if(c > 0) return 2;         //p在v的右边(下面)
    return 0;
}
bool Point_on_seg(Point p, Line v){  //0为不在线段上,1为在线段上
    return sgn(Cross(p - v.p1, v.p2 - v.p1)) == 0 && sgn(Dot(p - v.p1, p - v.p2)) <=0;
}
double Dis_point_line(Point p, Line v){     //点到直线的距离
    return fabs(Cross(p - v.p1, v.p2 - v.p1))/Dist(v.p1, v.p2);
}
Point Point_line_proj(Point p, Line v){        //点在直线上的投影
    double k = Dot(v.p2 - v.p1, p - v.p1)/Len2(v.p2 - v.p1);
    return v.p1 + (v.p2 - v.p1) * k;
}
Point Point_line_symmetry(Point p, Line v){       //点关于直线的对称点
    Point q = Point_line_proj(p, v);
    return Point(2 * q.x - p.x, 2 * q.y - p.y);
}
double Dis_point_seg(Point p, Segment v){           //点到线段的距离
    if(sgn(Dot(p - v.p1, v.p2 - v.p1)) < 0 || sgn(Dot(p - v.p2, v.p1 - v.p2)) < 0)
        return min(Dist(p, v.p1), Dist(p, v.p2));
    return Dis_point_line(p, v);
}
int Line_relation(Line v1, Line v2){         //两条直线的位置关系
    if(sgn(Cross(v1.p2 - v1.p1, v2.p2 - v2.p1)) == 0){
        if(Point_line_relation(v1.p1, v2) == 0)  return 1;         //重合
        else return 0;                                             //平行
    }
    return 2;                                                      //相交
}
Point Cross_point(Point a, Point b, Point c, Point d){           //求两条直线的交点,Line1:ab,Line2:cd,两直线不平行不共线
    double s1 = Cross(b - a, c - a);
    double s2 = Cross(b - a, d - a);
    return Point(c.x * s2 - d.x * s1, c.y * s2 - d.y * s1) / (s2 - s1);
}
bool Cross_segment(Point a, Point b, Point c, Point d){               //两线段是否规范相交 即如果一条线段的一个端点恰在另一条线段上则不视为相交;如果两条线段部分重合,也不视为相交。
    double c1 = Cross(b - a, c - a), c2 = Cross(b - a, d - a);
    double d1 = Cross(d - c, a - c), d2 = Cross(d - c, b - c);
    return sgn(c1) * sgn(c2) < 0 && sgn(d1) * sgn(d2) < 0;            //1:相交,0:不相交,端点重合不相交
}
bool Cross_segment1(Point a, Point b, Point c, Point d){    //两线段是否非规范相交
    return 
    max(a.x, b.x) >= min(c.x, d.x)&&
    max(c.x, d.x) >= min(a.x, b.x)&&
    max(a.y, b.y) >= min(c.y, d.y)&&
    max(c.y, d.y) >= min(a.y, b.y)&&
    sgn(Cross(b - a, c - a)) * sgn(Cross(b - a, d - a)) <= 0&&
    sgn(Cross(d - c, a - c)) * sgn(Cross(d - c, b - c)) <= 0;
    sgn(Cross(c - b, a - b)) * sgn(Cross(d - b, a - b)) <= 0&&
    sgn(Cross(a - d, c - d)) * sgn(Cross(b - d, c - d)) <= 0;
}
double Helen(double a, double b, double c){
    double p = (a + b + c)/2;
    return sqrt(p * (p - a) * (p - b) * (p - c));
}
int t, n, num, vis[maxn];
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>t;
    while(t--){
        cin>>n;
        memset(vis, 0, sizeof(vis));
        double boty = inf;
        double minn = inf, angle = 0;
        int pre= 0, first = 0;
        for(int i = 1; i <= n; i++){
            cin>>num>>P[i].x>>P[i].y; 
            if(P[i].y < boty){ 
                boty = P[i].y;
                pre = i;
            }
        }
        P[0] = {0, boty};
        cout<<n<<" "<<pre;
        vis[pre] = 1;
        int N = n;
        n--;
        int last = 0;
        while(n--){
            minn = inf;
            for(int i = 1; i <= N; i++){
                if(vis[i]) continue;
                angle = Angle(P[pre] - P[first], P[i] - P[pre]);
                if(angle - minn< eps){
                    minn = angle;
                    last = i;
                }
            }
            vis[last] = 1;
            first = pre;
            pre = last;
            cout<<" "<<pre;
        }
        cout<<endl;
    }
    return 0;
}

J - Kadj Squares (POJ - 3347)

AC Code:

#include<cstdio>
#include<vector>
#include<map>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<iomanip>
using namespace std;    
#define inf 0x3f3f3f3f
#define ll long long
#define eps 1e-10
#define endl "\n"
const int maxn = 60;
const int mod = 1e9 + 7;
const double pi = acos(-1.0);
int moven2[10][5] = {{1, 0, 0}, {-1, 0, 0}, {0, 1, 0}, {0, -1, 0}, {0, 0, 1}, {0, 0, -1}}; 
int moven1[10][5] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
int n, a[maxn], p[maxn], q[maxn];
vector<int>v;
int main() {
    // ios::sync_with_stdio(false);
    // cin.tie(0);cout.tie(0);
	while(~scanf("%d", &n)){
		if(n == 0) break;
		v.clear();
		memset(p, 0, sizeof(p));
		for(int i = 1;i <= n; i++)	
			scanf("%d",&a[i]);
		for(int i = 1;i <= n; i++){
			for(int j = 1; j <= i - 1; j++)
				p[i] = max(p[i],q[j] - abs(a[j] - a[i]));
			q[i] = p[i] + 2 * a[i]; 
		}
		for(int i = 1; i <= n; i++){
			for(int j = 1; j <= i - 1; j++){
				if(q[j] > p[i]){
					if(a[j] < a[i]) q[j] = p[i];
					else if(a[j] > a[i]) p[i] = q[j];
				}
			}
		}
		for(int i = 1; i <= n; i++){
			if(p[i] < q[i]) v.push_back(i);
		}
		for(int i = 0; i < v.size(); i++){
			printf("%d%c",v[i], i == v.size() - 1? '\n' : ' ');
		}
	}
	return 0;
}

K - An Easy Problem?! (POJ - 2826)

AC Code:

#include<cstdio>
#include<vector>
#include<map>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<iomanip>
using namespace std;    
const double pi = acos((double)(-1));
#define inf 0x3f3f3f3f
#define ll long long
#define eps 1e-8
const int maxn = 1000010;
const int mod = 1e9 + 7;
int sgn(double x){                 //判断x是否为0
    if(fabs(x) < eps) return 0;
    else return x < 0?-1:1;
}
int dcmp(double x, double y){      //比较两个浮点数   
    if(fabs(x - y) < eps) return 0;
    else return x < y?-1:1;
}
struct Point{
    double x,y;
    Point(){}
    Point(double x,double y):x(x),y(y){}
    Point operator + (Point B){return Point(x + B.x,y + B.y);}
    Point operator - (Point B){return Point(x - B.x,y - B.y);}
    Point operator * (double k){return Point(x*k,y*k);}
    Point operator / (double k){return Point(x/k,y/k);}
    bool operator == (Point B){return sgn(x - B.x) == 0 && sgn(y - B.y) == 0;}
    bool operator < (const Point &b)const{
        if(x == b.x) return y < b.y;
        return x < b.x;
    }
}P[maxn];
Point ch[maxn];
typedef Point Vector;   //用点的数据结构定义向量
struct Line{
    Point p1,p2;
    Line(){}
    Line(Point p1,Point p2):p1(p1),p2(p2){}
    Line(Point p,double angle){    //y = kx + b
        p1 = p;
        if(sgn(angle - pi/2) == 0){p2 = (p1 + Point(0,1));}
        else {p2 = (p1 + Point(1,tan(angle)));}
    }
    Line(double a,double b,double c){    //ax + by + c = 0
        if(sgn(a) == 0){
            p1 = Point(0, -c/b);
            p2 = Point(1, -c/b);
        }
        else if(sgn(b) == 0){
            p1 = Point(-c/a,0);
            p2 = Point(-c/a,1);
        }
        else{
            p1 = Point(0,-c/b);
            p2 = Point(1,(-c - a)/b);
        }
    }
}L[maxn];
typedef Line Segment;
double Dist(Point A,Point B){
    return sqrt((A.x - B.x)*(A.x - B.x) + (A.y - B.y)*(A.y - B.y));
}
double Dot(Vector A,Vector B){return A.x*B.x + A.y*B.y;}  //计算向量点积,>0锐角,<0钝角,=0直角 A·B = fabs(A)*fabs(B)*cos(angle)
double Len(Vector A){return sqrt(Dot(A,A));}             //计算向量长度
double Len2(Vector A){return Dot(A,A);}                  //向量长度的平方
double Angle(Vector A,Vector B){return acos(Dot(A,B)/Len(A)/Len(B));}   //计算两向量的夹角
double Cross(Vector A,Vector B){return A.x*B.y - A.y*B.x;}  //计算向量叉积,叉积有正负,A×B>0(B在A的逆时针方向),B×A<0   A×B = fabs(A)*fabs(B)*sin(angle)
double Area(Vector A,Vector B,Vector C){return Cross(B- A,C - A);} //以A为公共点的两向量构成的平行四边形面积
Vector Rotate(Vector A,double rad){          //计算一个点逆时针选择rad度后的点
    return Vector(A.x*cos(rad) - A.y*sin(rad), A.x*sin(rad) + A.y*cos(rad));
}
Vector Normal(Vector A){return Vector(-A.y/Len(A),A.x/Len(A));}   //求该向量的法向量
bool Parallel(Vector A,Vector B){return sgn(Cross(A,B)) == 0;}  //用叉积判断两向量是否平行或重合
int Point_line_relation(Point p, Line v){                       //点和线的位置关系
    int c = sgn(Cross(p - v.p1, v.p2 - v.p1));
    if(c < 0) return 1;         //p在v的左边(上面)
    if(c > 0) return 2;         //p在v的右边(下面)
    return 0;
}
bool Point_on_seg(Point p, Line v){  //0为不在线段上,1为在线段上
    return sgn(Cross(p - v.p1, v.p2 - v.p1)) == 0 && sgn(Dot(p - v.p1, p - v.p2)) <=0;
}
double Dis_point_line(Point p, Line v){     //点到直线的距离
    return fabs(Cross(p - v.p1, v.p2 - v.p1))/Dist(v.p1, v.p2);
}
Point Point_line_proj(Point p, Line v){        //点在直线上的投影
    double k = Dot(v.p2 - v.p1, p - v.p1)/Len2(v.p2 - v.p1);
    return v.p1 + (v.p2 - v.p1) * k;
}
Point Point_line_symmetry(Point p, Line v){       //点关于直线的对称点
    Point q = Point_line_proj(p, v);
    return Point(2 * q.x - p.x, 2 * q.y - p.y);
}
double Dis_point_seg(Point p, Segment v){           //点到线段的距离
    if(sgn(Dot(p - v.p1, v.p2 - v.p1)) < 0 || sgn(Dot(p - v.p2, v.p1 - v.p2)) < 0)
        return min(Dist(p, v.p1), Dist(p, v.p2));
    return Dis_point_line(p, v);
}
int Line_relation(Line v1, Line v2){         //两条直线的位置关系
    if(sgn(Cross(v1.p2 - v1.p1, v2.p2 - v2.p1)) == 0){
        if(Point_line_relation(v1.p1, v2) == 0)  return 1;         //重合
        else return 0;                                             //平行
    }
    return 2;                                                      //相交
}
Point Cross_point(Point a, Point b, Point c, Point d){           //求两条直线的交点,Line1:ab,Line2:cd,两直线不平行不共线
    double s1 = Cross(b - a, c - a);
    double s2 = Cross(b - a, d - a);
    return Point(c.x * s2 - d.x * s1, c.y * s2 - d.y * s1) / (s2 - s1);
}
bool Cross_segment(Point a, Point b, Point c, Point d){               //两线段是否规范相交 即如果一条线段的一个端点恰在另一条线段上则不视为相交;如果两条线段部分重合,也不视为相交。
    double c1 = Cross(b - a, c - a), c2 = Cross(b - a, d - a);
    double d1 = Cross(d - c, a - c), d2 = Cross(d - c, b - c);
    return sgn(c1) * sgn(c2) < 0 && sgn(d1) * sgn(d2) < 0;            //1:相交,0:不相交,端点重合不相交
}
bool Cross_segment1(Point a, Point b, Point c, Point d){    //两线段是否非规范相交
    return 
    max(a.x, b.x) >= min(c.x, d.x)&&
    max(c.x, d.x) >= min(a.x, b.x)&&
    max(a.y, b.y) >= min(c.y, d.y)&&
    max(c.y, d.y) >= min(a.y, b.y)&&
    sgn(Cross(b - a, c - a)) * sgn(Cross(b - a, d - a)) <= 0&&
    sgn(Cross(d - c, a - c)) * sgn(Cross(d - c, b - c)) <= 0;
    sgn(Cross(c - b, a - b)) * sgn(Cross(d - b, a - b)) <= 0&&
    sgn(Cross(a - d, c - d)) * sgn(Cross(b - d, c - d)) <= 0;
}
double Helen(double a, double b, double c){        //海伦公式
    double p = (a + b + c)/2;
    return sqrt(p * (p - a) * (p - b) * (p - c));
}

int Point_in_polygon(Point pt, Point *p, int n){         //判断点和多边形的位置关系
    for(int i = 0; i < n; i++){
        if(p[i] == pt) return 3;          //点在多边形的顶点上
    }
    for(int i = 0; i < n; i++){
        Line v = Line(p[i], p[(i + 1) % n]);
        if(Point_on_seg(pt, v)) return 2;      //点在多边形边上
    }
    int num = 0;
    for(int i = 0; i < n; i++){
        int j = (i + 1) % n;
        int c = sgn(Cross(pt - p[j], p[i] - p[j]));
        int u = sgn(p[i].y - pt.y);
        int v = sgn(p[j].y - pt.y);
        if(c > 0 && u < 0 && v >= 0) num++;
        if(c < 0 && u >= 0 && v < 0) num--;
    }
    return num != 0;      //1点在内部; 0点在外部
}
double Polygon_area(Point *p, int n){      //求多边形面积
    double area = 0;
    for (int i = 0; i < n; ++i)
			area +=  Cross(p[i], p[i + 1]);
	return area / 2;
}
Point Polygon_center(Point *p, int n){       //求多边形的重心
    Point ans(0, 0);
    if(Polygon_area(p, n) == 0) return ans;
    for(int i = 0; i < n; i++)
        ans = ans + (p[i] + p[(i + 1) % n]) * Cross(p[i], p[(i + 1) % n]);
    return ans / Polygon_area(p, n) / 6;
}
int Andrew(int n){     //求凸包
    sort(P, P + n);
    int len = 0;
    for(int i = 0; i < n; i++){
        while(len > 1 && sgn(Cross(ch[len] - ch[len - 1], P[i] - ch[len - 1])) == -1) len--;
        ch[++len] = P[i];
    }
    int k = len;
    for(int i = n - 2; i >= 0; i--){
        while(len > k && sgn(Cross(ch[len] - ch[len - 1], P[i] - ch[len - 1])) == -1) len--;
        ch[++len] = P[i];
    }
    return len;
}
int n, t;
int main(){
    // ios::sync_with_stdio(false);
    // cin.tie(0);cout.tie(0);
    scanf("%d", &t);
    while(t--){
        for(int i = 1; i <= 4; i++) scanf("%lf %lf", &P[i].x, &P[i].y);
        L[1] = Line(P[1], P[2]);
        L[2] = Line(P[3], P[4]);
        if(Line_relation(L[1], L[2]) == 0 || Line_relation(L[1], L[2]) == 1){
            printf("0.00\n");
            continue;
        }         
        if(Cross_segment1(P[1], P[2], P[3], P[4]) == 0){
            printf("0.00\n");
            continue;
        }
        if(P[1].y == P[2].y || P[3].y == P[4].y){
            printf("0.00\n");
            continue;
        }
        if(P[1].y < P[2].y) swap(P[1], P[2]);
        if(P[3].y < P[4].y) swap(P[3], P[4]);
        P[5].x = P[1].x;
        P[5].y = 10010;
        P[6].x = P[3].x;
        P[6].y = 10010;
        L[3] = Line(P[1], P[5]);
        L[4] = Line(P[3], P[6]);
        // cout<<P[1].x<<" "<<P[1].y<<endl;
        // cout<<P[2].x<<" "<<P[2].y<<endl;
        // cout<<P[3].x<<" "<<P[3].y<<endl;
        // cout<<P[6].x<<" "<<P[6].y<<endl; 
        if(Cross_segment1(P[1], P[5], P[3], P[4]) || Cross_segment1(P[3], P[6], P[1], P[2])){
            printf("0.00\n");
            continue;
        }
        P[7] = Cross_point(P[1], P[2], P[3], P[4]);
        // cout<<P[1].x<<" "<<P[1].y<<endl;
        // cout<<P[3].x<<" "<<P[3].y<<endl;
        if(P[1].y < P[3].y){
            P[8].y = P[1].y;
            if(P[3].x == P[4].x) P[8].x = P[3].x;
            else{
                double k = (P[3].y - P[4].y) / (P[3].x - P[4].x);
                P[8].x = P[3].x - (P[3].y - P[1].y) / k; 
            } 
            P[9] = P[1];
        }
        else {
            P[8].y = P[3].y;
            if(P[1].x == P[2].x) P[8].x = P[1].x;
            else{
                double k = (P[1].y - P[2].y) / (P[1].x - P[2].x);
                P[8].x = P[1].x - (P[1].y - P[3].y) / k;
                // cout<<P[1].x<<" "<<P[1].y<<endl;
                // cout<<P[2].x<<" "<<P[2].y<<endl;
                // cout<<k<<endl;
            }
            P[9] = P[3];
            // cout<<P[8].x<<" "<<P[8].y<<endl;
        }
        // cout<<P[8].x<<" "<<P[8].y<<endl;
        // cout<<P[9].x<<" "<<P[9].y<<endl;
        double area = 0;
        area +=  Cross(P[8] - P[7], P[7] - P[9]);
        area /= 2;
        area = fabs(area);
        printf("%.2f\n", area);
    }
    return 0;
}

L - Pipe (POJ - 1039)

AC Code:

#include<cstdio>
#include<vector>
#include<map>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<iomanip>
using namespace std;    
const double pi = acos((double)(-1));
#define inf 0x3f3f3f3f
#define ll long long
#define eps 1e-8
const int maxn = 1010;
const int mod = 1e9 + 7;
int sgn(double x){                 //判断x是否为0
    if(fabs(x) < eps) return 0;
    else return x < 0?-1:1;
}
int dcmp(double x, double y){      //比较两个浮点数   
    if(fabs(x - y) < eps) return 0;
    else return x < y?-1:1;
}
struct Point{
    double x,y;
    int id;
    Point(){}
    Point(double x,double y):x(x),y(y){}
    Point operator + (Point B){return Point(x + B.x,y + B.y);}
    Point operator - (Point B){return Point(x - B.x,y - B.y);}
    Point operator * (double k){return Point(x*k,y*k);}
    Point operator / (double k){return Point(x/k,y/k);}
    bool operator == (Point B){return sgn(x - B.x) == 0 && sgn(y - B.y) == 0;}
    bool operator < (const Point &b)const{           //凸包排序
        if(x == b.x) return y < b.y;
        return x < b.x;
    }
}P[maxn];
Point ch[maxn];

typedef Point Vector;   //用点的数据结构定义向量
struct Line{
    Point p1,p2;
    Line(){}
    Line(Point p1,Point p2):p1(p1),p2(p2){}
    Line(Point p,double angle){    //y = kx + b
        p1 = p;
        if(sgn(angle - pi/2) == 0){p2 = (p1 + Point(0,1));}
        else {p2 = (p1 + Point(1,tan(angle)));}
    }
    Line(double a,double b,double c){    //ax + by + c = 0
        if(sgn(a) == 0){
            p1 = Point(0, -c/b);
            p2 = Point(1, -c/b);
        }
        else if(sgn(b) == 0){
            p1 = Point(-c/a,0);
            p2 = Point(-c/a,1);
        }
        else{
            p1 = Point(0,-c/b);
            p2 = Point(1,(-c - a)/b);
        }
    }
}L[maxn];
typedef Line Segment;
double Dist(Point A,Point B){
    return sqrt((A.x - B.x)*(A.x - B.x) + (A.y - B.y)*(A.y - B.y));
}
double Dot(Vector A,Vector B){return A.x*B.x + A.y*B.y;}  //计算向量点积,>0锐角,<0钝角,=0直角 A·B = fabs(A)*fabs(B)*cos(angle)
double Len(Vector A){return sqrt(Dot(A,A));}             //计算向量长度
double Len2(Vector A){return Dot(A,A);}                  //向量长度的平方
double Angle(Vector A,Vector B){return acos(Dot(A,B)/Len(A)/Len(B));}   //计算两向量的夹角
double Cross(Vector A,Vector B){return A.x*B.y - A.y*B.x;}  //计算向量叉积,叉积有正负,A×B>0(B在A的逆时针方向),B×A<0   A×B = fabs(A)*fabs(B)*sin(angle)
double Area(Vector A,Vector B,Vector C){return Cross(B- A,C - A);} //以A为公共点的两向量构成的平行四边形面积
Vector Rotate(Vector A,double rad){          //计算一个点逆时针选择rad度后的点
    return Vector(A.x*cos(rad) - A.y*sin(rad), A.x*sin(rad) + A.y*cos(rad));
}
Vector Normal(Vector A){return Vector(-A.y/Len(A),A.x/Len(A));}   //求该向量的法向量
bool Parallel(Vector A,Vector B){return sgn(Cross(A,B)) == 0;}  //用叉积判断两向量是否平行或重合
int Point_line_relation(Point p, Line v){                       //点和线的位置关系
    int c = sgn(Cross(p - v.p1, v.p2 - v.p1));
    if(c < 0) return 1;         //p在v的左边(上面)
    if(c > 0) return 2;         //p在v的右边(下面)
    return 0;
}

bool Point_on_seg(Point p, Line v){  //0为不在线段上,1为在线段上
    return sgn(Cross(p - v.p1, v.p2 - v.p1)) == 0 && sgn(Dot(p - v.p1, p - v.p2)) <=0;
}

double Dis_point_line(Point p, Line v){     //点到直线的距离
    return fabs(Cross(p - v.p1, v.p2 - v.p1))/Dist(v.p1, v.p2);
}

Point Point_line_proj(Point p, Line v){        //点在直线上的投影
    double k = Dot(v.p2 - v.p1, p - v.p1)/Len2(v.p2 - v.p1);
    return v.p1 + (v.p2 - v.p1) * k;
}

Point Point_line_symmetry(Point p, Line v){       //点关于直线的对称点
    Point q = Point_line_proj(p, v);
    return Point(2 * q.x - p.x, 2 * q.y - p.y);
}

double Dis_point_seg(Point p, Segment v){           //点到线段的距离
    if(sgn(Dot(p - v.p1, v.p2 - v.p1)) < 0 || sgn(Dot(p - v.p2, v.p1 - v.p2)) < 0)
        return min(Dist(p, v.p1), Dist(p, v.p2));
    return Dis_point_line(p, v);
}

int Line_relation(Line v1, Line v2){         //两条直线的位置关系
    if(sgn(Cross(v1.p2 - v1.p1, v2.p2 - v2.p1)) == 0){
        if(Point_line_relation(v1.p1, v2) == 0)  return 1;         //重合
        else return 0;                                             //平行
    }
    return 2;                                                      //相交
}

Point Cross_point(Point a, Point b, Point c, Point d){           //求两条直线的交点,Line1:ab,Line2:cd,两直线不平行不共线
    double s1 = Cross(b - a, c - a);
    double s2 = Cross(b - a, d - a);
    return Point(c.x * s2 - d.x * s1, c.y * s2 - d.y * s1) / (s2 - s1);
}

bool Cross_segment(Point a, Point b, Point c, Point d){               //两线段是否规范相交 即如果一条线段的一个端点恰在另一条线段上则视为不相交;如果两条线段部分重合,也视为不相交。
    double c1 = Cross(b - a, c - a), c2 = Cross(b - a, d - a);
    double d1 = Cross(d - c, a - c), d2 = Cross(d - c, b - c);
    return sgn(c1) * sgn(c2) < 0 && sgn(d1) * sgn(d2) < 0;            //1:相交,0:不相交,端点重合不相交
}

bool Cross_segment1(Point a, Point b, Point c, Point d){    //两线段是否非规范相交
    return 
    max(a.x, b.x) >= min(c.x, d.x)&&
    max(c.x, d.x) >= min(a.x, b.x)&&
    max(a.y, b.y) >= min(c.y, d.y)&&
    max(c.y, d.y) >= min(a.y, b.y)&&
    sgn(Cross(b - a, c - a)) * sgn(Cross(b - a, d - a)) <= 0&&
    sgn(Cross(d - c, a - c)) * sgn(Cross(d - c, b - c)) <= 0;
    sgn(Cross(c - b, a - b)) * sgn(Cross(d - b, a - b)) <= 0&&
    sgn(Cross(a - d, c - d)) * sgn(Cross(b - d, c - d)) <= 0;
}

double Helen(double a, double b, double c){        //海伦公式
    double p = (a + b + c)/2;
    return sqrt(p * (p - a) * (p - b) * (p - c));
}

int Point_in_polygon(Point pt, Point *p, int n){         //判断点和多边形的位置关系
    for(int i = 0; i < n; i++){
        if(p[i] == pt) return 3;          //点在多边形的顶点上
    }
    for(int i = 0; i < n; i++){
        Line v = Line(p[i], p[(i + 1) % n]);
        if(Point_on_seg(pt, v)) return 2;      //点在多边形边上
    }
    int num = 0;
    for(int i = 0; i < n; i++){
        int j = (i + 1) % n;
        int c = sgn(Cross(pt - p[j], p[i] - p[j]));
        int u = sgn(p[i].y - pt.y);
        int v = sgn(p[j].y - pt.y);
        if(c > 0 && u < 0 && v >= 0) num++;
        if(c < 0 && u >= 0 && v < 0) num--;
    }
    return num != 0;      //1点在内部; 0点在外部
}

double Polygon_area(Point *p, int n){      //求多边形面积
    double area = 0;
    for (int i = 0; i < n; ++i)
			area +=  Cross(p[i], p[i + 1]);
	return area / 2;
}

Point Polygon_center(Point *p, int n){       //求多边形的重心
    Point ans(0, 0);
    if(Polygon_area(p, n) == 0) return ans;
    for(int i = 0; i < n; i++)
        ans = ans + (p[i] + p[(i + 1) % n]) * Cross(p[i], p[(i + 1) % n]);
    return ans / Polygon_area(p, n) / 6;
}

int Andrew(int n){		//返回凸包顶点数, 从0到top, ch[top] = ch[0]
	sort(P, P + n);
	int top = 1;
	ch[0] = P[0]; ch[1] = P[1];
	for(int i = 2;i < n; i++){
		while(top && Cross(P[i] - ch[top - 1], ch[top] - ch[top-1]) > eps) top--;
		ch[++top] = P[i];
	}
	int len = top;
	ch[++top] = P[n-2];
	for(int i = n-3;i >= 0; i--){
		while(top != len && Cross(P[i] - ch[top - 1], ch[top] - ch[top-1]) > eps) top--;
		ch[++top] = P[i];
	}
	return top;
}

bool judgetb(int n){           //判断是否为稳定凸包 即一条边上至少三个点
    for(int i = 1;i < n; i++){
		if((Cross(ch[i] - ch[i - 1], ch[i] - ch[i + 1])) != 0 && (Cross(ch[i] - ch[(i + 2) % n], ch[i + 1] - ch[(i + 2) % n])) != 0)
            return false;
	}
    return true;
}

int cmp(Point a,Point b){     //极角排序
    return Cross(a - P[0], b - P[0]) > 0;  
}

int n, flag;
int main(){
    // ios::sync_with_stdio(false);
    // cin.tie(0);cout.tie(0);
    Line v[maxn];
    Point p;
    while(~scanf("%d", &n)){
        if(n == 0) break;
        for(int i = 1; i <= n; i++){
            scanf("%lf %lf", &P[i].x, &P[i].y);
            P[i + n].x = P[i].x;
            P[i + n].y = P[i].y - 1;
        }
        for(int i = 2; i <= n; i++) L[i - 1] = Line(P[i - 1], P[i]); 
        for(int i = n + 2; i <= 2 * n; i++) L[i - 2] = Line(P[i - 1], P[i]);   // L[1] ~ L[2 * n - 2]
        for(int i = 1; i <= n; i++) v[i] = Line(P[i], P[i + n]); 
        double maxx = -inf;
        for(int i = 1; i <= n; i++){
            for(int j = n + 1; j <= 2 * n; j++){
                int sum = 0;
                flag = 0;
                if(i == j - n) continue;
                Line l = Line(P[i], P[j]);
                for(int k = 1; k <= n; k++){
                    p = Cross_point(l.p1, l.p2, v[k].p1, v[k].p2);
                    if(dcmp(p.y, P[k].y) <= 0 && dcmp(p.y, P[k + n].y) >= 0) sum++;
                    else{
                        if(k == 1) break;
                        else{
                            if(dcmp(p.y, P[k].y) == 1){
                                p = Cross_point(l.p1, l.p2, L[k - 1].p1, L[k - 1].p2);
                                if(dcmp(p.x, maxx) == 1) maxx = p.x;
                                break;
                            }
                            if(dcmp(p.y, P[k + n].y) == -1){
                                p = Cross_point(l.p1, l.p2, L[k + n - 2].p1, L[k + n - 2].p2);
                                if(dcmp(p.x, maxx) == 1) maxx = p.x;
                                break;
                            }
                        }
                    }
                }
                if(sum == n){
                    flag = 1;
                    break;
                }
            }
            if(flag) break;
        }
        if(flag) puts("Through all the pipe.");
        else printf("%.2f\n", maxx);
    }
    return 0;
}

M - Geometric Shapes (POJ - 3449)

思路: 思路很简单就是判断每个图形的线段是否非规范相交,就是输入输出有点恶心,我用了二维结构体进行存储,感觉方便了很多。然后就是每次输入的时候都输出一下,可以及时发现哪里出问题了。

AC Code:

#include<cstdio>
#include<vector>
#include<map>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<iomanip>
#include<queue>
using namespace std;
#define ll long long
const int maxn = 30;
const double pi = acos((double)(-1));
#define eps 1e-8
char ch, shape[maxn];
int num, insert[maxn][maxn];
int sgn(double x){                 //判断x是否为0
    if(fabs(x) < eps) return 0;
    else return x < 0?-1:1;
}
struct Point{
    double x,y;
    Point(){}
    Point(double x,double y):x(x),y(y){}
    Point operator + (Point B){return Point(x + B.x,y + B.y);}
    Point operator - (Point B){return Point(x - B.x,y - B.y);}
    Point operator * (double k){return Point(x*k,y*k);}
    Point operator / (double k){return Point(x/k,y/k);}
    bool operator == (Point B){return sgn(x - B.x) == 0 && sgn(y - B.y) == 0;}
    bool operator < (const Point &b)const{           //凸包排序
        if(x == b.x) return y < b.y;
        return x < b.x;
    }
}P[maxn][maxn];
typedef Point Vector;
struct Line{
    Point p1,p2;
    int size;
    Line(){};
    Line(Point p1,Point p2):p1(p1),p2(p2){}
    Line(Point p,double angle){    //y = kx + b
        p1 = p;
        if(sgn(angle - pi/2) == 0){p2 = (p1 + Point(0,1));}
        else {p2 = (p1 + Point(1,tan(angle)));}
    }
    Line(double a,double b,double c){    //ax + by + c = 0
        if(sgn(a) == 0){
            p1 = Point(0, -c/b);
            p2 = Point(1, -c/b);
        }
        else if(sgn(b) == 0){
            p1 = Point(-c/a,0);
            p2 = Point(-c/a,1);
        }
        else{
            p1 = Point(0,-c/b);
            p2 = Point(1,(-c - a)/b);
        }
    }
}L[maxn][maxn];
double Cross(Vector A,Vector B){return A.x*B.y - A.y*B.x;}  
bool Cross_segment1(Point a, Point b, Point c, Point d){   
 //两线段是否非规范相交
    return 
    max(a.x, b.x) >= min(c.x, d.x)&&
    max(c.x, d.x) >= min(a.x, b.x)&&
    max(a.y, b.y) >= min(c.y, d.y)&&
    max(c.y, d.y) >= min(a.y, b.y)&&
    sgn(Cross(b - a, c - a)) * sgn(Cross(b - a, d - a)) <= 0&&
    sgn(Cross(d - c, a - c)) * sgn(Cross(d - c, b - c)) <= 0;
}
int main() {
    while(~scanf(" %c", &ch)) {
        if(ch == '.')
            break;
        if(ch == '-') {
            // for(int i = 0; i < 26; i++)
            //     printf("%d %d\n", i, L[i][0].size);
            for(int i = 0; i < 26; i++) {
                if(L[i][0].size == 0) continue;
                for(int j = 0; j < 26; j++) {
                    if(i == j || L[j][0].size == 0) continue;
                    int f = 0;
                    for(int k = 0; k < L[i][0].size; k++) {
                        for(int p = 0; p < L[j][0].size; p++) {
                            if(Cross_segment1(L[i][k].p1, L[i][k].p2, L[j][p].p1, L[j][p].p2) == 1) {
                                f = 1;
                                insert[i][j] = 1;
                                break;
                            }
                        }
                        if(f)
                            break;
                    }
                }
            }
            // for(int i = 0; i < 26; i++) {
            //     for(int j = 0; j < 26; j++)
            //         printf("%d %d %d\n", i, j, insert[i][j]);
            // }                                                                // true
            for(int i = 0; i < 26; i++) {
                if(L[i][0].size == 0) continue;
                int ans = 0;
                for(int j = 0; j < 26; j++) {
                    if(insert[i][j]) ans++;
                }
                if(ans == 0)
                    printf("%c has no intersections\n", i + 'A');
                else if(ans == 1) {
                    for(int j = 0; j < 26; j++) {
                        if(insert[i][j]) {
                            printf("%c intersects with %c\n", i + 'A', j + 'A');
                            break;
                        }
                    }
                }
                else if(ans == 2) {
                    int cnt = 0;
                    for(int j = 0; j < 26; j++) {
                        if(insert[i][j]) {
                            if(cnt == 0) {
                                printf("%c intersects with %c and ", i + 'A', j + 'A');
                                cnt++;
                            }
                            else if(cnt == 1) {
                                printf("%c\n", j + 'A');
                                break;
                            }
                        }
                    }
                }
                else{
                    int cnt = 0;
                    for(int j = 0; j < 26; j++) {
                        if(insert[i][j]) {
                            if(cnt == 0) {
                                printf("%c intersects with %c, ", i + 'A', j + 'A');
                                cnt++;
                            }
                            else if(cnt == ans - 1) {
                                printf("and %c\n", j + 'A');
                                break;
                            }
                            else{
                                printf("%c, ", j + 'A');
                                cnt++;
                            }
                        }
                    }
                }
            }
            memset(P, 0, sizeof(P));
            memset(L, 0, sizeof(L));
            memset(insert, 0, sizeof(insert));
            printf("\n");
            continue;
        }
        int num = ch - 'A';
        scanf("%s", shape);
        // printf("%c %s\n", ch, shape);
        if(shape[0] == 's') {
            scanf(" (%lf,%lf) (%lf,%lf)", &P[num][0].x, &P[num][0].y, &P[num][2].x, &P[num][2].y);
            // printf("%f %f %f %f\n", P[num][0].x, P[num][0].y, P[num][1].x, P[num][1].y);
            P[num][1].x = (P[num][0].x + P[num][0].y + P[num][2].x - P[num][2].y) / 2;
            P[num][1].y = (-P[num][0].x + P[num][0].y + P[num][2].x + P[num][2].y) / 2;
            P[num][3].x = (P[num][0].x - P[num][0].y + P[num][2].x + P[num][2].y) / 2;
            P[num][3].y = (P[num][0].x + P[num][0].y - P[num][2].x + P[num][2].y) / 2;
            for(int i = 0; i < 4; i++) {
                L[num][i] = Line(P[num][i], P[num][(i + 1) % 4]);
            }  
            L[num][0].size = 4;
            // printf("%d %d\n", num, L[num][0].size);                                   
        }                                                                                   //true
        else if(shape[0] == 'l') {
            scanf(" (%lf,%lf) (%lf,%lf)", &P[num][0].x, &P[num][0].y, &P[num][1].x, &P[num][1].y);
            L[num][0] = Line(P[num][0], P[num][1]);
            L[num][0].size = 1;
            // printf("%f %f %f %f\n", L[num][0].p1.x, L[num][0].p1.y, L[num][0].p2.x, L[num][0].p2.y);
            // printf("%d %d\n", num, L[num][0].size);
        }                                                                                 // true
        else if(shape[0] == 't') {
            scanf(" (%lf,%lf) (%lf,%lf) (%lf,%lf)", &P[num][0].x, &P[num][0].y, &P[num][1].x, &P[num][1].y, &P[num][2].x, &P[num][2].y);
            for(int i = 0; i < 3; i++) {
                L[num][i] = Line(P[num][i], P[num][(i + 1) % 3]);
            }
            // for(int i = 0; i < 3; i++)
            //     printf("%f %f %f %f\n", L[num][i].p1.x, L[num][i].p1.y, L[num][i].p2.x, L[num][i].p2.y);    
            L[num][0].size = 3;
            // printf("%d %d\n", num, L[num][0].size);          
        }                                                                                // true
        else if(shape[0] == 'p') {
            int cnt;
            scanf("%d", &cnt);
            for(int i = 0; i < cnt; i++) {
                scanf(" (%lf,%lf)", &P[num][i].x, &P[num][i].y);
            }
            for(int i = 0; i < cnt; i++) {
                L[num][i] = Line(P[num][i], P[num][(i + 1) % cnt]);
            }            
            // for(int i = 0; i < cnt; i++)
            //     printf("%f %f %f %f\n", L[num][i].p1.x, L[num][i].p1.y, L[num][i].p2.x, L[num][i].p2.y);  
            L[num][0].size = cnt;
            // printf("%d %d\n", num, L[num][0].size);
        }                                                                              // true
        else{
            scanf(" (%lf,%lf) (%lf,%lf) (%lf,%lf)", &P[num][0].x, &P[num][0].y, &P[num][1].x, &P[num][1].y, &P[num][2].x, &P[num][2].y);
            P[num][3].x = P[num][0].x + P[num][2].x - P[num][1].x;
            P[num][3].y = P[num][0].y + P[num][2].y - P[num][1].y;
            for(int i = 0; i < 4; i++) {
                L[num][i] = Line(P[num][i], P[num][(i + 1) % 4]);
            }          
            // for(int i = 0; i < 4; i++)
            //     printf("%f %f %f %f\n", L[num][i].p1.x, L[num][i].p1.y, L[num][i].p2.x, L[num][i].p2.y);    
            L[num][0].size = 4;
            // printf("%d %d\n", num, L[num][0].size);
            // printf("%d\n", L[num][3].size);          
        }                                                                           // true
    }
    system("pause");
    return 0;
}

N - A Round Peg in a Ground Hole (POJ - 1548)

思路:

  • 如果不是凸包输出"HOLE IS ILL-FORMED"
  • 如果是凸包但圆不在凸包内输出"PEG WILL NOT FIT"
  • 如果是凸包并且圆在凸包内输出"PEG WILL FIT"

对于如何判断圆是否在凸包内可先判断圆心是否在凸包内,再判断圆到每条边的距离(三角形面积除底)是否小于半径。
这题点的坐标可能是乱序的,所以需要极角排序。

AC Code:

#include<cstdio>
#include<vector>
#include<map>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<iomanip>
#include<queue>
using namespace std;
#define ll long long
const int maxn = 1010;
const double pi = acos((double)(-1));
#define eps 1e-8
int n;
int sgn(double x){                 //判断x是否为0
    if(fabs(x) < eps) return 0;
    else return x < 0?-1:1;
}
struct Point{
    double x,y;
    Point(){}
    Point(double x,double y):x(x),y(y){}
    Point operator + (Point B){return Point(x + B.x,y + B.y);}
    Point operator - (Point B){return Point(x - B.x,y - B.y);}
    Point operator * (double k){return Point(x*k,y*k);}
    Point operator / (double k){return Point(x/k,y/k);}
    bool operator == (Point B){return sgn(x - B.x) == 0 && sgn(y - B.y) == 0;}
    bool operator < (const Point &b)const{           //凸包排序
        if(x == b.x) return y < b.y;
        return x < b.x;
    }
}P[maxn], ch[maxn];
typedef Point Vector;
double Cross(Vector A,Vector B){return A.x*B.y - A.y*B.x;}  
double Dot(Vector A,Vector B){return A.x*B.x + A.y*B.y;}  
double Dist(Point A,Point B){
    return sqrt((A.x - B.x)*(A.x - B.x) + (A.y - B.y)*(A.y - B.y));
}
struct Line{
    Point p1,p2;
    Line(){};
    Line(Point p1,Point p2):p1(p1),p2(p2){}
    Line(Point p,double angle){    //y = kx + b
        p1 = p;
        if(sgn(angle - pi/2) == 0){p2 = (p1 + Point(0,1));}
        else {p2 = (p1 + Point(1,tan(angle)));}
    }
    Line(double a,double b,double c){    //ax + by + c = 0
        if(sgn(a) == 0){
            p1 = Point(0, -c/b);
            p2 = Point(1, -c/b);
        }
        else if(sgn(b) == 0){
            p1 = Point(-c/a,0);
            p2 = Point(-c/a,1);
        }
        else{
            p1 = Point(0,-c/b);
            p2 = Point(1,(-c - a)/b);
        }
    }
}L[maxn];
int Andrew(int n) {   //0 ~ top - 1  ch[top] = ch[0]
    sort(P, P + n);
    int top = 0;
    for(int i = 0; i < n; i++) {
        while(top > 1 && Cross(ch[top - 1] - ch[top - 2], P[i] - ch[top - 2]) < 0) {
            top--;
        }
        ch[top++] = P[i];
    }
    int k = top;
    for(int i = n - 2; i >= 0; i--) {
        while(top > k && Cross(ch[top - 1] - ch[top - 2], P[i] - ch[top - 2]) < 0) {
            top--;
        }
        ch[top++] = P[i];
    }
    if(n > 1)
        top--;
    return top;
}
bool Point_on_seg(Point p, Line v){  //0为不在线段上,1为在线段上
    return sgn(Cross(p - v.p1, v.p2 - v.p1)) == 0 && 
    sgn(Dot(p - v.p1, p - v.p2)) <=0;
}
int Point_in_polygon(Point pt, Point *p, int n){         //判断点和多边形的位置关系
    for(int i = 0; i < n; i++){
        if(p[i] == pt) return 3;          //点在多边形的顶点上
    }
    for(int i = 0; i < n; i++){
        Line v = Line(p[i], p[(i + 1) % n]);
        if(Point_on_seg(pt, v)) return 2;      //点在多边形边上
    }
    int num = 0;
    for(int i = 0; i < n; i++){
        int j = (i + 1) % n;
        int c = sgn(Cross(pt - p[j], p[i] - p[j]));
        int u = sgn(p[i].y - pt.y);
        int v = sgn(p[j].y - pt.y);
        if(c > 0 && u < 0 && v >= 0) num++;
        if(c < 0 && u >= 0 && v < 0) num--;
    }
    return num != 0;      //1点在内部; 0点在外部
}
struct Circle{
    double x, y, r;
}C;
bool check() {
    Point p = Point(C.x, C.y);
    if(Point_in_polygon(p, P, n) == 0) return false;
    for(int i = 0; i < n; i++) {
        if(sgn(C.r - fabs(Cross(P[i] - p, P[(i + 1) % n] - p) / Dist(P[i], P[(i + 1) % n]))) > 0 ) {
            return false;
        } 
    }
    return true;
}
int cmp(Point a,Point b){     //极角排序
    Point pp = Point(0, 0);
    return Cross(a - pp, b - pp) > 0;  
}
int main() {
    while(~scanf("%d", &n)) {
        if(n < 3)
            break;
        scanf("%lf %lf %lf", &C.r, &C.x, &C.y);
        for(int i = 0; i < n; i++)
            scanf("%lf %lf", &P[i].x, &P[i].y);
        int len = Andrew(n);
        if(len == n) {
            sort(P, P + n, cmp);
            if(check()) {
                puts("PEG WILL FIT");
            }
            else{
                puts("PEG WILL NOT FIT");
            }
        }
        else{
            puts("HOLE IS ILL-FORMED");
        }
    }  
    system("pause");
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值