基础计算几何

计算几何把几个模板写好,然后根据不同题目分析即可。

 

必要代码:

const double eps=1e-8;
const double PI=acos(-1.0);
typedef double lf;
int sgn(double x)
{
    if(fabs(x)<eps) return 0;
    if(x<0) return -1;
    else return 1;
}
View Code

 

二维平面上的点:

struct vec{
    lf x,y;
    vec(lf x=0,lf y=0):x(x),y(y){}
    vec operator-(const vec &b){return vec(x-b.x,y-b.y);}
    vec operator+(const vec &b){return vec(x+b.x,y+b.y);}
    vec operator*(lf k){return vec(k*x,k*y);}
    lf operator ^(const vec &b){return x*b.y-y*b.x;}
    lf len(){return hypot(x,y);}
    lf sqr(){return x*x+y*y;}
    /*截取*/vec trunc(lf k=1){return *this*(k/len());}
    /*逆时针旋转*/vec rotate(double th){lf c=cos(th),s=sin(th); return vec(x*c-y*s,x*s+y*c);}
}q[maxn],pp;
lf cross(vec a,vec b){return a.x*b.y-a.y*b.x;};
lf cross(vec a,vec b,vec c){return cross(a-b,b-c);}
lf dot(vec a,vec b){return a.x*b.x+a.y*b.y;}
bool cmp_xy(const vec &a,const vec &b){return make_pair(a.x,a.y)<make_pair(b.x,b.y);}
bool cmp_atan(const vec &a,const vec &b){return atan2(a.x,a.y)<atan2(b.x,b.y);}
/*输出*/ostream &operator<<(ostream &o,const vec &v){return o<<'('<<v.x<<','<<v.y<<')';}
View Code

 

判断两条线段是否相交

bool judge(vec a,vec b,vec c,vec d){ //线段ab和线段cd
    #define SJ(x) max(a.x,b.x)<min(c.x,d.x)\
    || max(c.x,d.x)<min(a.x,b.x)
    if(SJ(x) || SJ(y))return 0;
    #define SJ2(a,b,c,d) cross(a-b,a-c)*cross(a-b,a-d)<=0
    return SJ2(a,b,c,d) && SJ2(c,d,a,b);
}
View Code

 

判断线段与直线是否相交

bool judge(vec a,vec b,vec c,vec d)
{ 
    return sgn(cross(d,a,b))*sgn(cross(c,a,b))<=0;
}
View Code

 

POJ - 2318

二分+叉积寻找位置即可

#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cctype>
#include<iostream>
#include<algorithm>
//#include<chrono>
#include<vector>
#include<list>
#include<queue>
#include<string>
#include<set>
#include<map>
//#include<unordered_set>
//#include<unordered_map>
#define debug frelimiten("r.txt","r",stdin)
#define mp make_pair
#define ri register int
using namespace std;
typedef long long ll;
typedef double lf;
typedef pair<int, int> pii;
const int maxn = 10500+10;
const int INF = 0x3f3f3f3f; 
const int mod = 998244353;
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;}
ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
struct vec{
    lf x,y;
    vec(lf x=0,lf y=0):x(x),y(y){}
    vec operator-(const vec &b){return vec(x-b.x,y-b.y);}
    vec operator+(const vec &b){return vec(x+b.x,y+b.y);}
    vec operator*(lf k){return vec(k*x,k*y);}
    lf len(){return hypot(x,y);}
    lf sqr(){return x*x+y*y;}
    /*截取*/vec trunc(lf k=1){return *this*(k/len());}
    /*逆时针旋转*/vec rotate(double th){lf c=cos(th),s=sin(th); return vec(x*c-y*s,x*s+y*c);}
}a[maxn],pp;
lf cross(vec a,vec b){return a.x*b.y-a.y*b.x;};
lf cross(vec a,vec b,vec c){return cross(a-b,b-c);}
lf dot(vec a,vec b){return a.x*b.x+a.y*b.y;}
bool cmp_xy(const vec &a,const vec &b){return make_pair(a.x,a.y)<make_pair(b.x,b.y);}
bool cmp_atan(const vec &a,const vec &b){return atan2(a.x,a.y)<atan2(b.x,b.y);}
/*输出*/ostream &operator<<(ostream &o,const vec &v){return o<<'('<<v.x<<','<<v.y<<')';}
int vis[maxn],n,m,i,x1,y1,x2,y2,x,y,u,l;
int main()
{
    while (~scanf("%d",&n))
    {
        if (n==0) break;
        //scanf("%d%d%d%d%d",&m,&x1,&y1,&x2,&y2);
        memset(vis,0,sizeof(vis));
        m=read(),x1=read(),y1=read(),x2=read(),y2=read();
        for (i=0;i<n;i++)
        {
            scanf("%d%d",&u,&l);
            a[i]=vec(u,y1);
            a[i+n+1]=vec(l,y2);
        }
        a[n]=vec(x2,y1),a[2*n+1]=vec(x2,y2);
        for (i=1;i<=m;i++)
        {
            x=read(),y=read();
            pp=vec(x,y);
            int ll=0,rr=n;
            int tmp=0;
            while (ll<=rr)
            {
                int mid=(ll+rr)>>1;
                if (cross(pp,a[mid],a[mid+n+1])<0)
                {
                    rr=mid-1;
                    tmp=mid;
                }
                else ll=mid+1;
            }
            vis[tmp]++;
            //vis[rr]++;
        }
        for (i=0;i<=n;i++)
        {
            cout<<i<<": "<<vis[i]<<endl;
        }
        cout<<endl;
    }
    return 0;
}
View Code

 

POJ - 2398

与上一题相同,只需多个排序

#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cctype>
#include<iostream>
#include<algorithm>
//#include<chrono>
#include<vector>
#include<list>
#include<queue>
#include<string>
#include<set>
#include<map>
//#include<unordered_set>
//#include<unordered_map>
#define debug frelimiten("r.txt","r",stdin)
#define mp make_pair
#define ri register int
using namespace std;
typedef long long ll;
typedef double lf;
typedef pair<int, int> pii;
const int maxn = 10500+10;
const int INF = 0x3f3f3f3f; 
const int mod = 998244353;
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;}
ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
struct vec{
    lf x,y;
    vec(lf x=0,lf y=0):x(x),y(y){}
    vec operator-(const vec &b){return vec(x-b.x,y-b.y);}
    vec operator+(const vec &b){return vec(x+b.x,y+b.y);}
    vec operator*(lf k){return vec(k*x,k*y);}
    lf len(){return hypot(x,y);}
    lf sqr(){return x*x+y*y;}
    /*截取*/vec trunc(lf k=1){return *this*(k/len());}
    /*逆时针旋转*/vec rotate(double th){lf c=cos(th),s=sin(th); return vec(x*c-y*s,x*s+y*c);}
}pp;
struct node
{
    vec s,t;
}a[maxn];
lf cross(vec a,vec b){return a.x*b.y-a.y*b.x;};
lf cross(vec a,vec b,vec c){return cross(a-b,b-c);}
lf dot(vec a,vec b){return a.x*b.x+a.y*b.y;}
bool cmp_xy(const node &a,const node &b){return make_pair(a.s.x,a.s.y)<make_pair(b.s.x,b.s.y);}
bool cmp_atan(const vec &a,const vec &b){return atan2(a.x,a.y)<atan2(b.x,b.y);}
/*输出*/ostream &operator<<(ostream &o,const vec &v){return o<<'('<<v.x<<','<<v.y<<')';}
int vis[maxn],ans[maxn],n,m,i,x1,y1,x2,y2,x,y,u,l;
int main()
{
    while (~scanf("%d",&n))
    {
        if (n==0) break;
        //scanf("%d%d%d%d%d",&m,&x1,&y1,&x2,&y2);
        memset(vis,0,sizeof(vis));
        memset(ans,0,sizeof(ans));
        m=read(),x1=read(),y1=read(),x2=read(),y2=read();
        for (i=0;i<n;i++)
        {
            scanf("%d%d",&u,&l);
            a[i].s=vec(u,y1);
            a[i].t=vec(l,y2);
        }
        a[n].s=vec(x2,y1),a[n].t=vec(x2,y2);
        sort(a,a+n+1,cmp_xy);
        for (i=1;i<=m;i++)
        {
            x=read(),y=read();
            pp=vec(x,y);
            int ll=0,rr=n;
            int tmp=0;
            while (ll<=rr)
            {
                int mid=(ll+rr)>>1;
                if (cross(pp,a[mid].s,a[mid].t)<0)
                {
                    rr=mid-1;
                    tmp=mid;
                }
                else ll=mid+1;
            }
            vis[tmp]++;
        }
        
        for (i=0;i<=n;i++) 
        {
            if (vis[i]>0) ans[vis[i]]++;
        }
        cout<<"Box"<<endl;
        for (i=1;i<=n;i++)
        {
            if (ans[i]>0)
                cout<<i<<": "<<ans[i]<<endl;
        }
    }
    return 0;
}
View Code

 

※POJ - 3304

看了证明才懂这题的思路:

1:把问题转化为是否存在一条直线与每条线段都有交点。证明:若存在一条直线l和所有线段相交,作一条直线m和l垂直,则m就是题中要求的直线,所有线段投影的一个公共点即为垂足。

2:枚举两两线段的各一个端点,连一条直线,再判断剩下的线段是否都和这条直线有交点。证明:若有l和所有线段相交,则可保持l和所有线段相交,左右平移l到和某一线段交于端点停止(“移不动了”)。然后绕这个交点旋转。也是转到“转不动了”(和另一线段交于其一个端点)为止。这样就找到了一个新的l满足题意,而且经过其中两线段的端点。

#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cctype>
#include<iostream>
#include<algorithm>
//#include<chrono>
#include<vector>
#include<list>
#include<queue>
#include<string>
#include<set>
#include<map>
//#include<unordered_set>
//#include<unordered_map>
#define debug frelimiten("r.txt","r",stdin)
#define mp make_pair
#define ri register int
using namespace std;
typedef long long ll;
typedef double lf;
typedef pair<int, int> pii;
const int maxn = 10500+10;
const int INF = 0x3f3f3f3f; 
const int mod = 998244353;
const double eps=1e-8;
const double PI=acos(-1.0);
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;}
ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
int sgn(double x)
{
    if(fabs(x)<eps) return 0;
    if(x<0) return -1;
    else return 1;
}
struct vec{
    lf x,y;
    vec(lf x=0,lf y=0):x(x),y(y){}
    vec operator-(const vec &b){return vec(x-b.x,y-b.y);}
    vec operator+(const vec &b){return vec(x+b.x,y+b.y);}
    vec operator*(lf k){return vec(k*x,k*y);}
//    lf operator *(const vec &b){return x*b.x + y*b.y;}
    lf operator ^(const vec &b){return x*b.y-y*b.x;}
    lf len(){return hypot(x,y);}
    lf sqr(){return x*x+y*y;}
    /*截取*/vec trunc(lf k=1){return *this*(k/len());}
    /*逆时针旋转*/vec rotate(double th){lf c=cos(th),s=sin(th); return vec(x*c-y*s,x*s+y*c);}
};
struct Line
{
    vec s,t;
}a[maxn];
lf cross(vec a,vec b){return a.x*b.y-a.y*b.x;};
lf cross(vec a,vec b,vec c){return cross(a-b,b-c);}
lf dot(vec a,vec b){return a.x*b.x+a.y*b.y;}
bool cmp_xy(const Line &a,const Line &b){return make_pair(a.s.x,a.s.y)<make_pair(b.s.x,b.s.y);}
bool cmp_atan(const vec &a,const vec &b){return atan2(a.x,a.y)<atan2(b.x,b.y);}
/*输出*/ostream &operator<<(ostream &o,const vec &v){return o<<'('<<v.x<<','<<v.y<<')';}
//double xmult(vec p0,vec p1,vec p2) 
//{
//    return (p1-p0)^(p2-p0);
//}
double dist(vec a,vec b)
{
    return sqrt(dot(b-a,b-a));
}
bool judge(vec a,vec b,vec c,vec d){ 
    return sgn(cross(d,a,b))*sgn(cross(c,a,b))<=0;
}
bool flag;
int t,i,n,j;
double xx,yy;
bool check(vec x,vec y,int n)
{
    if (sgn(dist(x,y)==0)) return false;
        for (ri k=1;k<=n;k++)
            if (!judge(x,y,a[k].s,a[k].t)) return false;
    return true;
}
int main()
{
    t=read();
    while (t--)
    {
        n=read();
        for (i=1;i<=n;i++)
        {
            scanf("%lf%lf",&xx,&yy);
            a[i].s=vec(xx,yy);
            scanf("%lf%lf",&xx,&yy);
            a[i].t=vec(xx,yy);
        }
        flag=false;
        for (i=1;i<=n&&!flag;i++)
            for (j=1;j<=n&&!flag;j++)
            {
                if (check(a[i].s,a[j].t,n) || check(a[i].s,a[j].s,n) || check(a[i].t,a[j].t,n) || check(a[i].t,a[j].s,n))
                {
                    flag=true;
                    break;
                }
            }
        if (flag) printf("Yes!\n");
            else printf("No!\n");
    }
    return 0;
}
View Code

 

POJ - 1556

首先肯定要贴着点走,这时只需一个个离散每个点的位置,求一遍最短路即可。

#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cctype>
#include<iostream>
#include<algorithm>
//#include<chrono>
#include<vector>
#include<list>
#include<queue>
#include<string>
#include<set>
#include<map>
//#include<unordered_set>
//#include<unordered_map>
#define debug frelimiten("r.txt","r",stdin)
#define mp make_pair
#define ri register int
using namespace std;
typedef long long ll;
typedef double lf;
typedef pair<int, int> pii;
const int maxn = 10500+10;
const int INF = 0x3f3f3f3f; 
const int mod = 998244353;
const double eps=1e-8;
const double PI=acos(-1.0);
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;}
ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
int sgn(double x)
{
    if(fabs(x)<eps) return 0;
    if(x<0) return -1;
    else return 1;
}
struct vec{
    lf x,y;
    vec(lf x=0,lf y=0):x(x),y(y){}
    vec operator-(const vec &b){return vec(x-b.x,y-b.y);}
    vec operator+(const vec &b){return vec(x+b.x,y+b.y);}
    vec operator*(lf k){return vec(k*x,k*y);}
    lf operator ^(const vec &b){return x*b.y-y-b.x;}
    lf len(){return hypot(x,y);}
    lf sqr(){return x*x+y*y;}
    /*截取*/vec trunc(lf k=1){return *this*(k/len());}
    /*逆时针旋转*/vec rotate(double th){lf c=cos(th),s=sin(th); return vec(x*c-y*s,x*s+y*c);}
}b[maxn];
lf cross(vec a,vec b){return a.x*b.y-a.y*b.x;};
lf cross(vec a,vec b,vec c){return cross(a-b,b-c);}
lf dot(vec a,vec b){return a.x*b.x+a.y*b.y;}
bool cmp_xy(const vec &a,const vec &b){return make_pair(a.x,a.y)<make_pair(b.x,b.y);}
bool cmp_atan(const vec &a,const vec &b){return atan2(a.x,a.y)<atan2(b.x,b.y);}
/*输出*/ostream &operator<<(ostream &o,const vec &v){return o<<'('<<v.x<<','<<v.y<<')';}
double dist(vec a,vec b)
{
    return sqrt(dot((a-b),(a-b)));
}
bool judge(vec a,vec b,vec c,vec d){ //线段ab和线段cd
    #define SJ(x) max(a.x,b.x)<min(c.x,d.x)\
    || max(c.x,d.x)<min(a.x,b.x)
    if(SJ(x) || SJ(y))return 0;
    #define SJ2(a,b,c,d) cross(a-b,a-c)*cross(a-b,a-d)<=0
    return SJ2(a,b,c,d) && SJ2(c,d,a,b);
}
int n,i,j,k;
double x,y1,y2,y3,y4,dis[505][505];
bool flag;
int main()
{
    while (~scanf("%d",&n))    
    {
        if (n==-1) break;
        b[0]=vec(0,5);
        for (i=0;i<n;i++)
        {
            scanf("%lf",&x);
            scanf("%lf%lf%lf%lf",&y1,&y2,&y3,&y4);
            b[i*4+1]=vec(x,y1);
            b[i*4+2]=vec(x,y2);
            b[i*4+3]=vec(x,y3);
            b[i*4+4]=vec(x,y4);
        }
        b[n*4+1]=vec(10,5);
        memset(dis,0,sizeof(dis));
        for (i=0;i<=4*n+1;i++)
            for (j=i+1;j<=4*n+1;j++) 
            {
                int xx=(i-1)/4;
                int yy=(j-1)/4;
                if (i==0) xx=-1;
                flag=true;
                for (k=xx+1;k<yy;k++)
                {
                    if (judge(b[4*k+1],vec(b[4*k+1].x,0),b[i],b[j]))
                    {
                        flag=false;
                        break;
                    }
                    if (judge(b[4*k+2],b[4*k+3],b[i],b[j]))
                    {
                        flag=false;
                        break;
                    }
                    if (judge(b[4*k+4],vec(b[4*k+4].x,10),b[i],b[j]))
                    {
                        flag=false;
                        break;
                    }    
                }
                dis[i][j]=(flag?dist(b[i],b[j]):INF);
                dis[j][i]=dis[i][j];
            }
        for (k=0;k<=4*n+1;k++)
            for (i=0;i<=4*n+1;i++)
                for (j=0;j<=4*n+1;j++)
                    dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
        printf("%.2f\n", dis[0][4 * n + 1]);
    }    
    return 0;
}
View Code

 

POJ - 2653

求线段与线段相交

#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cctype>
#include<iostream>
#include<algorithm>
//#include<chrono>
#include<vector>
#include<list>
#include<queue>
#include<string>
#include<set>
#include<map>
//#include<unordered_set>
//#include<unordered_map>
#define debug frelimiten("r.txt","r",stdin)
#define mp make_pair
#define ri register int
using namespace std;
typedef long long ll;
typedef double lf;
typedef pair<int, int> pii;
const int maxn = 100500+10;
const int INF = 0x3f3f3f3f; 
const int mod = 998244353;
const double eps=1e-8;
const double PI=acos(-1.0);
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;}
ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
int sgn(double x)
{
    if(fabs(x)<eps) return 0;
    if(x<0) return -1;
    else return 1;
}
struct vec{
    lf x,y;
    vec(lf x=0,lf y=0):x(x),y(y){}
    vec operator-(const vec &b){return vec(x-b.x,y-b.y);}
    vec operator+(const vec &b){return vec(x+b.x,y+b.y);}
    vec operator*(lf k){return vec(k*x,k*y);}
    lf operator ^(const vec &b){return x*b.y-y-b.x;}
    lf len(){return hypot(x,y);}
    lf sqr(){return x*x+y*y;}
    /*截取*/vec trunc(lf k=1){return *this*(k/len());}
    /*逆时针旋转*/vec rotate(double th){lf c=cos(th),s=sin(th); return vec(x*c-y*s,x*s+y*c);}
}b[maxn];
lf cross(vec a,vec b){return a.x*b.y-a.y*b.x;};
lf cross(vec a,vec b,vec c){return cross(a-b,b-c);}
lf dot(vec a,vec b){return a.x*b.x+a.y*b.y;}
bool cmp_xy(const vec &a,const vec &b){return make_pair(a.x,a.y)<make_pair(b.x,b.y);}
bool cmp_atan(const vec &a,const vec &b){return atan2(a.x,a.y)<atan2(b.x,b.y);}
/*输出*/ostream &operator<<(ostream &o,const vec &v){return o<<'('<<v.x<<','<<v.y<<')';}
bool judge(vec a,vec b,vec c,vec d){ //线段ab和线段cd
    #define SJ(x) max(a.x,b.x)<min(c.x,d.x)\
    || max(c.x,d.x)<min(a.x,b.x)
    if(SJ(x) || SJ(y))return 0;
    #define SJ2(a,b,c,d) cross(a-b,a-c)*cross(a-b,a-d)<=0
    return SJ2(a,b,c,d) && SJ2(c,d,a,b);
}
struct Line
{
    vec s,t;
}a[maxn];
int n,i,j,num;
bool vis[maxn],flag,firstt;
double x1,y1,x2,y2;
int main()
{
    while (~scanf("%d",&n))
    {
        if (n==0) return 0;
        for (i=1;i<=n;i++)
        {
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            a[i].s=vec(x1,y1);
            a[i].t=vec(x2,y2);
        }
        memset(vis,0,sizeof(vis));
        printf("Top sticks:");
        firstt=0;
        for (i=1;i<=n;i++)
        {
            flag=0;
            for (j=i+1;j<=n;j++)
            {
                if (judge(a[i].s,a[i].t,a[j].s,a[j].t)) 
                {
                    flag=1;
                    break;
                }
            }
            if (!flag) 
            {
                if (!firstt) firstt=1;
                    else printf(",");
                printf(" %d",i);
            }
        }    
        puts(".");
    }
}
View Code

 

POJ - 1066

中点通过,与通过线的任何方式无差异,问题还是转化为起点到终点通过几条线。

#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cctype>
#include<iostream>
#include<algorithm>
//#include<chrono>
#include<vector>
#include<list>
#include<queue>
#include<string>
#include<set>
#include<map>
#define debug frelimiten("r.txt","r",stdin)
#define mp make_pair
#define ri register int
using namespace std;
typedef long long ll;
typedef double lf;
typedef pair<int, int> pii;
const int maxn = 1050+10;
const int INF = 0x3f3f3f3f; 
const int mod = 998244353;
const double eps=1e-8;
const double PI=acos(-1.0);
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;}
ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
int sgn(double x)
{
    if(fabs(x)<eps) return 0;
    if(x<0) return -1;
    else return 1;
}
struct vec{
    lf x,y;
    vec(lf x=0,lf y=0):x(x),y(y){}
    vec operator-(const vec &b){return vec(x-b.x,y-b.y);}
    vec operator+(const vec &b){return vec(x+b.x,y+b.y);}
    vec operator*(lf k){return vec(k*x,k*y);}
    lf operator ^(const vec &b){return x*b.y-y-b.x;}
    lf len(){return hypot(x,y);}
    lf sqr(){return x*x+y*y;}
    /*截取*/vec trunc(lf k=1){return *this*(k/len());}
    /*逆时针旋转*/vec rotate(double th){lf c=cos(th),s=sin(th); return vec(x*c-y*s,x*s+y*c);}
}q[maxn],pp;
lf cross(vec a,vec b){return a.x*b.y-a.y*b.x;};
lf cross(vec a,vec b,vec c){return cross(a-b,b-c);}
lf dot(vec a,vec b){return a.x*b.x+a.y*b.y;}
bool cmp_xy(const vec &a,const vec &b){return make_pair(a.x,a.y)<make_pair(b.x,b.y);}
bool cmp_atan(const vec &a,const vec &b){return atan2(a.x,a.y)<atan2(b.x,b.y);}
/*输出*/ostream &operator<<(ostream &o,const vec &v){return o<<'('<<v.x<<','<<v.y<<')';}
bool judge(vec a,vec b,vec c,vec d){ //线段ab和线段cd
    #define SJ(x) max(a.x,b.x)<min(c.x,d.x)\
    || max(c.x,d.x)<min(a.x,b.x)
    if(SJ(x) || SJ(y))return 0;
    #define SJ2(a,b,c,d) cross(a-b,a-c)*cross(a-b,a-d)<=0
    return SJ2(a,b,c,d) && SJ2(c,d,a,b);
}
int n,i,minn,j,num;
double targetx,targety,x1,y1,x2,y2;
int main()
{
    n=read();
    for (i=1;i<=2*n;i+=2) 
    {
        scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
        q[i]=vec(x1,y1);
        q[i+1]=vec(x2,y2);
    }
    scanf("%lf%lf",&targetx,&targety);
    pp=vec(targetx,targety);
    minn=INF;
    for (i=1;i<=2*n;i++)
    {
        num=0;
        for (j=1;j<=2*n;j+=2)
        {
            if (judge(q[i],pp,q[j],q[j+1])) num++;
        }
        minn=min(minn,num);
    }
    if (!n) printf("Number of doors = 1");
    else printf("Number of doors = %d",minn);
    return 0;
}
View Code

 

POJ - 1410

在矩阵里面也算相交

#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cctype>
#include<iostream>
#include<algorithm>
//#include<chrono>
#include<vector>
#include<list>
#include<queue>
#include<string>
#include<set>
#include<map>
#define debug frelimiten("r.txt","r",stdin)
#define mp make_pair
#define ri register int
using namespace std;
typedef long long ll;
typedef double lf;
typedef pair<int, int> pii;
const int maxn = 1050+10;
const int INF = 0x3f3f3f3f; 
const int mod = 998244353;
const double eps=1e-8;
const double PI=acos(-1.0);
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;}
ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
int sgn(double x)
{
    if(fabs(x)<eps) return 0;
    if(x<0) return -1;
    else return 1;
}
struct vec{
    lf x,y;
    vec(lf x=0,lf y=0):x(x),y(y){}
    vec operator-(const vec &b){return vec(x-b.x,y-b.y);}
    vec operator+(const vec &b){return vec(x+b.x,y+b.y);}
    vec operator*(lf k){return vec(k*x,k*y);}
    lf operator ^(const vec &b){return x*b.y-y-b.x;}
    lf len(){return hypot(x,y);}
    lf sqr(){return x*x+y*y;}
    /*截取*/vec trunc(lf k=1){return *this*(k/len());}
    /*逆时针旋转*/vec rotate(double th){lf c=cos(th),s=sin(th); return vec(x*c-y*s,x*s+y*c);}
}q[maxn],pp;
lf cross(vec a,vec b){return a.x*b.y-a.y*b.x;};
lf cross(vec a,vec b,vec c){return cross(a-b,b-c);}
lf dot(vec a,vec b){return a.x*b.x+a.y*b.y;}
bool cmp_xy(const vec &a,const vec &b){return make_pair(a.x,a.y)<make_pair(b.x,b.y);}
bool cmp_atan(const vec &a,const vec &b){return atan2(a.x,a.y)<atan2(b.x,b.y);}
/*输出*/ostream &operator<<(ostream &o,const vec &v){return o<<'('<<v.x<<','<<v.y<<')';}
bool judge(vec a,vec b,vec c,vec d){ //线段ab和线段cd
    #define SJ(x) max(a.x,b.x)<min(c.x,d.x)\
    || max(c.x,d.x)<min(a.x,b.x)
    if(SJ(x) || SJ(y))return 0;
    #define SJ2(a,b,c,d) cross(a-b,a-c)*cross(a-b,a-d)<=0
    return SJ2(a,b,c,d) && SJ2(c,d,a,b);
}
struct Line
{
    vec s,t;
}line,rectangle[5];
bool flag;
int n;
double x,y,xx,yy;
int main()
{
    n=read();
    while (n--)
    {
        scanf("%lf%lf",&x,&y);
        line.s=vec(x,y);
        scanf("%lf%lf",&x,&y);
        line.t=vec(x,y);
        scanf("%lf%lf",&x,&y);
        scanf("%lf%lf",&xx,&yy);
        if (x>xx) swap(x,xx);
        if (y<yy) swap(y,yy);
        rectangle[1].s=vec(x,y),rectangle[1].t=vec(x,yy);
        rectangle[2].s=vec(x,y),rectangle[2].t=vec(xx,y);
        rectangle[3].s=vec(xx,yy),rectangle[3].t=vec(xx,y);
        rectangle[4].s=vec(xx,yy),rectangle[4].t=vec(x,yy);
        flag=0;
        for (int i=1;i<=4;i++)
        {
            if (judge(line.s,line.t,rectangle[i].s,rectangle[i].t))
            {
                flag=1;
                break;
            }
        }
        if (x<=line.s.x && line.s.x<=xx && yy<=line.s.y && line.s.y<=y) flag=1;
        if (x<=line.t.x && line.t.x<=xx && yy<=line.t.y && line.t.y<=y) flag=1;
        if (flag) printf("T\n");
            else printf("F\n");
    }
    return 0;
}
View Code

 

POJ - 1696

极角排序

#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cctype>
#include<iostream>
#include<algorithm>
//#include<chrono>
#include<vector>
#include<list>
#include<queue>
#include<string>
#include<set>
#include<map>
#define debug frelimiten("r.txt","r",stdin)
#define mp make_pair
#define ri register int
using namespace std;
typedef long long ll;
typedef double lf;
typedef pair<int, int> pii;
const int maxn = 1050+10;
const int INF = 0x3f3f3f3f; 
const int mod = 998244353;
const double eps=1e-8;
const double PI=acos(-1.0);
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;}
ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
int sgn(double x)
{
    if(fabs(x)<eps) return 0;
    if(x<0) return -1;
    else return 1;
}
struct vec{
    lf x,y;
    int num;
    vec(lf x=0,lf y=0):x(x),y(y){}
    vec operator-(const vec &b){return vec(x-b.x,y-b.y);}
    vec operator+(const vec &b){return vec(x+b.x,y+b.y);}
    vec operator*(lf k){return vec(k*x,k*y);}
    lf operator ^(const vec &b){return x*b.y-y-b.x;}
    lf len(){return hypot(x,y);}
    lf sqr(){return x*x+y*y;}
    /*截取*/vec trunc(lf k=1){return *this*(k/len());}
    /*逆时针旋转*/vec rotate(double th){lf c=cos(th),s=sin(th); return vec(x*c-y*s,x*s+y*c);}
}p[maxn];
lf cross(vec a,vec b){return a.x*b.y-a.y*b.x;};
lf cross(vec a,vec b,vec c){return cross(a-b,b-c);}
lf dot(vec a,vec b){return a.x*b.x+a.y*b.y;}
bool cmp_xy(const vec &a,const vec &b){return make_pair(a.x,a.y)<make_pair(b.x,b.y);}
bool cmp_atan(const vec &a,const vec &b){return atan2(a.x,a.y)<atan2(b.x,b.y);}
/*输出*/ostream &operator<<(ostream &o,const vec &v){return o<<'('<<v.x<<','<<v.y<<')';}
int t,n,i,ans[maxn];
bool cmp(vec p1,vec p2)
{
    double temp;
    temp=cross(p1,p2,p[i-1]);
    if (sgn(temp)>0) return true;
    else if (sgn(temp)==0 && ((p1-p[i-1]).len())<((p2-p[i-1]).len())) return true;
    return false;
}

int main()
{
    t=read();
    while (t--)
    {
        n=read();
        for (i=0;i<n;i++)
        {
            p[i].num=read();
            cin>>p[i].x>>p[i].y;
            if (p[i].y<p[0].y) swap(p[0],p[i]);
        }
//        sort(p+1,p+n,cmp);
        ans[0]=p[0].num;
        for (i=1;i<n;i++)
        {
            sort(p+i,p+n,cmp);
            ans[i]=p[i].num;
        }
        cout<<n;
        for (i=0;i<n;i++)
            printf(" %d",ans[i]);
        cout<<endl;
    }
    return 0;
}
View Code

 

POJ - 3347

这题看了别人的思路感觉十分的巧妙,首先我们把所以线增大√2倍,然后再通过对前者矩阵的比较,算出左端点和右端点,这时就可以一个个判断是否有遮挡即可。

#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cctype>
#include<iostream>
#include<algorithm>
//#include<chrono>
#include<vector>
#include<list>
#include<queue>
#include<string>
#include<set>
#include<map>
#define debug frelimiten("r.txt","r",stdin)
#define mp make_pair
#define ri register int
using namespace std;
typedef long long ll;
typedef double lf;
typedef pair<int, int> pii;
const int maxn = 1050+10;
const int INF = 0x3f3f3f3f; 
const int mod = 998244353;
const double eps=1e-8;
const double PI=acos(-1.0);
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;}
ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
int sgn(double x)
{
    if(fabs(x)<eps) return 0;
    if(x<0) return -1;
    else return 1;
}
struct vec{
    lf x,y;
    int num;
    vec(lf x=0,lf y=0):x(x),y(y){}
    vec operator-(const vec &b){return vec(x-b.x,y-b.y);}
    vec operator+(const vec &b){return vec(x+b.x,y+b.y);}
    vec operator*(lf k){return vec(k*x,k*y);}
    lf operator ^(const vec &b){return x*b.y-y-b.x;}
    lf len(){return hypot(x,y);}
    lf sqr(){return x*x+y*y;}
    /*截取*/vec trunc(lf k=1){return *this*(k/len());}
    /*逆时针旋转*/vec rotate(double th){lf c=cos(th),s=sin(th); return vec(x*c-y*s,x*s+y*c);}
}p[maxn];
lf cross(vec a,vec b){return a.x*b.y-a.y*b.x;};
lf cross(vec a,vec b,vec c){return cross(a-b,b-c);}
lf dot(vec a,vec b){return a.x*b.x+a.y*b.y;}
bool cmp_xy(const vec &a,const vec &b){return make_pair(a.x,a.y)<make_pair(b.x,b.y);}
bool cmp_atan(const vec &a,const vec &b){return atan2(a.x,a.y)<atan2(b.x,b.y);}
/*输出*/ostream &operator<<(ostream &o,const vec &v){return o<<'('<<v.x<<','<<v.y<<')';}
struct node
{
    int l,r,len;
};
int n,i,j;
int solve(node a,node b)
{
    if (a.len<=b.len) return b.l+b.len+a.len;
        else return b.r+b.len-a.len;
}
int main()
{
    node a[55];
    while (~scanf("%d",&n),n)
    {
        for (i=0;i<n;i++)
        {
            scanf("%d",&a[i].len);
            a[i].l=0;
            for (j=0;j<i;j++)
                a[i].l=max(a[i].l,solve(a[i],a[j]));
            a[i].r=a[i].l+2*a[i].len;
        }
        for (i=1;i<n;i++)
            for (j=0;j<i;j++)
            {
                if (a[i].len<a[j].len && a[i].l<a[j].r) a[i].l=a[j].r;
                else if (a[i].len>a[j].len && a[i].l<a[j].r) a[j].r=a[i].l;
            }
        for (i=0;i<n;i++)
            if (a[i].l<a[i].r) printf("%d ",i+1);
        printf("\n");
    }
    return 0;
} 
View Code

 

POJ - 1039

首先如果存在能通过这个管道的线,那么我们对这条线稍微转一下角度,必会有先交到两个点,所以枚举两个端点,如果这条过这两个端点的直线能够通过整个管道,则得到答案。

若不能,我们每次取射到的最远距离即可。

#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<iomanip>
#include<cctype>
#include<iostream>
#include<algorithm>
//#include<chrono>
#include<vector>
#include<list>
#include<queue>
#include<string>
#include<set>
#include<map>
#define debug frelimiten("r.txt","r",stdin)
#define mp make_pair
#define ri register int
using namespace std;
typedef long long ll;
typedef double lf;
typedef pair<int, int> pii;
const int maxn = 1050+10;
const int INF = 0x3f3f3f3f; 
const int mod = 998244353;
const double eps=1e-8;
const double PI=acos(-1.0);
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;}
ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
int sgn(double x)
{
    if(fabs(x)<eps) return 0;
    if(x<0) return -1;
    else return 1;
}
struct vec{
    lf x,y;
    int num;
    vec(lf x=0,lf y=0):x(x),y(y){}
    vec operator-(const vec &b){return vec(x-b.x,y-b.y);}
    vec operator+(const vec &b){return vec(x+b.x,y+b.y);}
    vec operator*(lf k){return vec(k*x,k*y);}
    lf operator ^(const vec &b){return x*b.y-y-b.x;}
    lf len(){return hypot(x,y);}
    lf sqr(){return x*x+y*y;}
    /*截取*/vec trunc(lf k=1){return *this*(k/len());}
    /*逆时针旋转*/vec rotate(double th){lf c=cos(th),s=sin(th); return vec(x*c-y*s,x*s+y*c);}
}down[maxn],up[maxn];
lf cross(vec a,vec b){return a.x*b.y-a.y*b.x;};
lf cross(vec a,vec b,vec c){return cross(a-b,b-c);}
lf dot(vec a,vec b){return a.x*b.x+a.y*b.y;}
bool cmp_xy(const vec &a,const vec &b){return make_pair(a.x,a.y)<make_pair(b.x,b.y);}
bool cmp_atan(const vec &a,const vec &b){return atan2(a.x,a.y)<atan2(b.x,b.y);}
/*输出*/ostream &operator<<(ostream &o,const vec &v){return o<<'('<<v.x<<','<<v.y<<')';}
bool judge(vec a,vec b,vec c,vec d)
{ 
    return (sgn(cross(a,b,c))*sgn(cross(a,b,d))<=0);
}
double solve(vec a,vec b,vec c,vec d)
{
    lf area1=cross(a,b,c);
    lf area2=cross(a,b,d);
    int num1=sgn(area1);
    int num2=sgn(area2);
    if (num1*num2<0) return (area2*c.x-area1*d.x)/(area2-area1);
    if (num1*num2==0)
    {
        if (num1==0) return c.x;
        else return d.x;
    }
    return -INF;
}
double ans,maxx;
int n,i,j,k;
bool flag;
int main()
{
    while (~scanf("%d",&n))
    {
        if (n==0) return 0;
        for (i=1;i<=n;i++)
        {
            scanf("%lf%lf",&up[i].x,&up[i].y);
            down[i].x=up[i].x;
            down[i].y=up[i].y-1;
        }
        maxx=-INF;
        flag=false;
        for (i=1;i<=n&&!flag;i++)
            for (j=1;j<=n&&!flag;j++)
                if (i!=j)
                {
                    for (k=1;k<=n;k++)
                        if (!judge(up[i],down[j],up[k],down[k])) break;
                    if (k>n) 
                    {
                        flag=true;
                    }
                    else 
                    if (k>max(i,j))
                    {
                        ans=solve(up[i],down[j],up[k],up[k-1]);
                        if (maxx<ans) maxx=ans;
                        ans=solve(up[i],down[j],down[k],down[k-1]);
                        if (maxx<ans) maxx=ans;
                    }
                }
        if(flag)
            cout<<"Through all the pipe."<<endl;
        else
            cout<<fixed<<setprecision(2)<<maxx<<endl;
    }
}
View Code

 

posted @ 2020-06-01 14:27  Y-KnightQin  阅读(143)  评论(0编辑  收藏  举报