[kuangbin带你飞]专题十三 基础计算几何(Except M N)

附上做这套专题的模板(该专题只有点线面的关系所以这些模板就够了)

const db EPS=1e-9;
inline int sign(db a){return a<-EPS?-1:a>EPS;}
inline int cmp(db a,db b){return sign(a-b);}
#define cross(p1,p2,p3) ((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y))
#define ocross(p1,p2,p3) sign(cross(p1,p2,p3))
struct P{
    db x,y;
    void add(db xx,db yy){
        x=xx,y=yy;
    }
    P(){}
    P(db _x,db _y) : x(_x), y(_y){}
    P operator+(P p){return {x+p.x,y+p.y};}
    P operator-(P p){return {x-p.x,y-p.y};}
    P operator*(db d){return{x*d,y*d};}
    P operator/(db d){return{x/d,y/d};}
    bool operator<(P p)const {
        int c=cmp(x,p.x);
        if(c) return c==-1;
        return cmp(y,p.y)==-1;
    }
    bool operator==(P o)const {
        return cmp(x,o.x)==0&&cmp(y,o.y)==0;
    }
};
bool chkLL(P p1,P p2,P q1,P q2){
    db a1=cross(q1,q2,p1);
    db a2=-cross(q1,q2,p2);
    return sign(a1+a2)!=0;
}
P isLL(P p1,P p2,P q1,P q2){
    db a1=cross(q1,q2,p1),a2=-cross(q1,q2,p2);
    return (p1*a2+p2*a1)/(a1+a2);
}
bool intersect(db l1,db r1,db l2,db r2){
    if(l1>r1) swap(l1,r1); if(l2>r2) swap(l2,r2);
    return !(cmp(r1,l2)==-1|cmp(r2,l1)==-1);
}
bool isSS(P p1,P p2,P q1,P q2){
    //cout<<ocross(p1,p2,q1)*ocross(p1,p2,q2)<<' '<<ocross(p1,p2,q1)*ocross(p1,p2,q2)<<endl;
    return intersect(p1.x,p2.x,q1.x,q2.x) && intersect(p1.y,p2.y,q1.y,q2.y) &&
    ocross(p1,p2,q1)*ocross(p1,p2,q2)<=0&&ocross(q1,q2,p1)*ocross(q1,q2,p2)<=0;
}
bool isSS_strict(P p1,P p2,P q1,P q2){
    return ocross(p1,p2,q1)*ocross(p1,p2,q2)<0&&ocross(q1,q2,p1)*ocross(q1,q2,p2)<0;
}
bool isSS_ch(P p1,P p2,P q1,P q2){
    return ocross(p1,p2,q1)==0&&ocross(p1,p2,q2)==0&&ocross(q1,q2,p1)==0&&ocross(q1,q2,p2)==0;
}
db dep(db a,db b,db c,db d){
    return a*c+b*d;
}
db det(db a,db b,db c,db d){
    return a*d-b*c;
}

模板内容不进行详细介绍大致就是线段线段相交、直线直线相交

A poj2318

题解:

题意大致是给定几个划分区域以及一些点的坐标,问这些点在哪些区域内(题意明确规定点不在线段上)
很容易想到的一个思路就是从左往右搜线段若点第一次出现在线段左侧,则该区域就是答案(判断线段的左右用 d e t det det叉乘即可)

代码:

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <ctime>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
#define PB push_back
#define MP make_pair
#define INF 1073741824
#define inf 1152921504606846976
#define pi 3.14159265358979323846
//#pragma comment(linker,"/STACK:10240000,10240000")
const int N=5200,M=2e6;
const long long mod=1e9+7;
inline int read(){int ret=0;char ch=getchar();bool f=1;for(;!isdigit(ch);ch=getchar()) f^=!(ch^'-');for(;isdigit(ch);ch=getchar()) ret=(ret<<1)+(ret<<3)+ch-48;return f?ret:-ret;}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}//ÄæÔª
//int head[N],NEXT[N],ver[N],tot;void link(int u,int v){ver[++tot]=v;NEXT[tot]=head[u];head[u]=tot;}

int x[N],y[N],x1,x2,y1,y2;
int ans[N];
int det(int xx,int yy,int a,int b){
    return b*xx-a*yy;
}
int judge(int zi,int xx,int yy){
    //if(yy>=y1||yy<=y2||xx<=x1||xx>=x2) return 0;
    //int res=det();
    int res=det(x[zi]-y[zi],y1-y2,xx-y[zi],yy-y2);
    //cout<<res<<endl;
    if(res<0) return -1;
    else if(res==0) return 0;
    else return 1;

}
int main(){
    //freopen("1.txt","r",stdin);
    int n,m;
    int u,v;
    while(~scanf("%d",&n)){
        if(n==0) break;
        memset(ans,0,sizeof(ans));
        scanf("%d%d%d%d%d",&m,&x1,&y1,&x2,&y2);
        for(int i=1;i<=n;i++){
            scanf("%d%d",&x[i],&y[i]);
        }
        for(int i=1;i<=m;i++){
            scanf("%d%d",&u,&v);
            bool mark=false;
            for(int j=1;j<=n;j++){
                if(judge(j,u,v)==1){
                    ans[j-1]++;
                    mark=true;
                    break;
                }
            }
            if(!mark) ans[n]++;
        }
        for(int i=0;i<=n;i++){
            printf("%d: %d\n",i,ans[i]);
        }
        puts("");
    }
    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}

B poj-2398

此题只要把上一题代码粘过来统计有t个物品的盒子有几个即可

C poj3304

题解:

给定n条线段问存不存在一条直线使得直线与所有线段都相交。

思路即两两枚举每个线段的端点相连之后check是否满足题意(直线与线段相交原理还是叉乘)

代码:

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <ctime>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
#define PB push_back
#define MP make_pair
#define INF 1073741824
#define inf 1152921504606846976
#define pi 3.14159265358979323846
#define EPS 1e-8
//#pragma comment(linker,"/STACK:10240000,10240000")
const int N=3e5+7,M=2e6;
const long long mod=1e9+7;
inline int read(){int ret=0;char ch=getchar();bool f=1;for(;!isdigit(ch);ch=getchar()) f^=!(ch^'-');for(;isdigit(ch);ch=getchar()) ret=(ret<<1)+(ret<<3)+ch-48;return f?ret:-ret;}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}//ÄæÔª
//int head[N],NEXT[N],ver[N],tot;void link(int u,int v){ver[++tot]=v;NEXT[tot]=head[u];head[u]=tot;}
int n;
db x1[N],y1[N];
int det(db a,db b,db c,db d){
    db tmp=a*d-b*c;
    if(tmp==0) return 0;
    else if(tmp>0) return 1;
    else return -1;
}
bool judge(int zi,int zj){
    bool mark=true;
    for(int i=1;i<=n;i++){
        int res1=det(x1[zj]-x1[zi],y1[zj]-y1[zi],x1[i]-x1[zi],y1[i]-y1[zi]);
        int res2=det(x1[zj]-x1[zi],y1[zj]-y1[zi],x1[i+n]-x1[zi],y1[i+n]-y1[zi]);
        if(!res1||!res2) continue;
        if(res1==-res2) continue;
        mark=false;
        break;
    }
    if(!mark) return false;
    return true;
    //cout<<res1<<' '<<res2<<' '<<res3<<' '<<res4<<endl;
}
void solve(){
    //printf("%.20f\n",EPS*EPS);
    for(int i=1;i<=2*n;i++){
        for(int j=i+1;j<=2*n;j++){
            if((x1[i]-x1[j])*(x1[i]-x1[j])+(y1[i]-y1[j])*(y1[i]-y1[j])<=EPS*EPS) continue;
            if(judge(i,j)){
                puts("Yes!");
                return ;
            }
        }
    }
    puts("No!");
}
int main(){
    //freopen("1.txt","r",stdin);
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%lf%lf%lf%lf",&x1[i],&y1[i],&x1[i+n],&y1[i+n]);
        }
        solve();
    }
    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}

D poj1269

判断线段与线段相交、平行、重合问题,套入相应板子即可

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <ctime>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
#define PB push_back
#define MP make_pair
#define INF 1073741824
#define inf 1152921504606846976
#define pi 3.14159265358979323846
//#pragma comment(linker,"/STACK:10240000,10240000")
const int N=3e5+7,M=2e6;
const long long mod=1e9+7;
inline int read(){int ret=0;char ch=getchar();bool f=1;for(;!isdigit(ch);ch=getchar()) f^=!(ch^'-');for(;isdigit(ch);ch=getchar()) ret=(ret<<1)+(ret<<3)+ch-48;return f?ret:-ret;}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}//ÄæÔª
//int head[N],NEXT[N],ver[N],tot;void link(int u,int v){ver[++tot]=v;NEXT[tot]=head[u];head[u]=tot;}
const db EPS=1e-9;
inline int sign(db a){return a<-EPS?-1:a>EPS;}
inline int cmp(db a,db b){return sign(a-b);}
#define cross(p1,p2,p3) ((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y))
#define ocross(p1,p2,p3) sign(cross(p1,p2,p3))
struct P{
    db x,y;
    P(){}
    P(db _x,db _y) : x(_x), y(_y){}
    P operator+(P p){return {x+p.x,y+p.y};}
    P operator-(P p){return {x-p.x,y-p.y};}
    P operator*(db d){return{x*d,y*d};}
    P operator/(db d){return{x/d,y/d};}
    bool operator<(P p)const {
        int c=cmp(x,p.x);
        if(c) return c==-1;
        return cmp(y,p.y)==-1;
    }
    bool operator==(P o)const {
        return cmp(x,o.x)==0&&cmp(y,o.y)==0;
    }
};
bool chkLL(P p1,P p2,P q1,P q2){
    db a1=cross(q1,q2,p1);
    db a2=-cross(q1,q2,p2);
    //printf("%.2f %.2f\n",a1,a2);
    return sign(a1+a2)!=0;
}
P isLL(P p1,P p2,P q1,P q2){
    db a1=cross(q1,q2,p1),a2=-cross(q1,q2,p2);
    return (p1*a2+p2*a1)/(a1+a2);
}
int main(){
    //freopen("1.txt","r",stdin);
    int t;
    puts("INTERSECTING LINES OUTPUT");
    scanf("%d",&t);
    while(t--){
        P p1,p2,p3,p4;
        scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&p1.x,&p1.y,&p2.x,&p2.y,&p3.x,&p3.y,&p4.x,&p4.y);
        if(!chkLL(p1,p2,p3,p4)){
            if(ocross(p1,p2,p3)==0) puts("LINE");
            else puts("NONE");
        }
        else {
            P ans=isLL(p1,p2,p3,p4);
            printf("POINT %.2f %.2f\n",ans.x,ans.y);
        }
    }
    puts("END OF OUTPUT");

    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}

E poj1556

题解:

题意是给一张有挡板的图问从一段走到另一段的最短路

这题只需要耐心枚举点之后check这两个点之间是否有线段相交的情况,若没有将这两点相连,距离为dist。
简图完成后跑一遍dij即可

代码:

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <ctime>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
#define PB push_back
#define MP make_pair
#define INF 1073741824
#define inf 1152921504606846976
#define pi 3.14159265358979323846
//#pragma comment(linker,"/STACK:10240000,10240000")
const int N=600,M=2e6;
const long long mod=1e9+7;
inline int read(){int ret=0;char ch=getchar();bool f=1;for(;!isdigit(ch);ch=getchar()) f^=!(ch^'-');for(;isdigit(ch);ch=getchar()) ret=(ret<<1)+(ret<<3)+ch-48;return f?ret:-ret;}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}//ÄæÔª
db wei[M];
int head[N],NEXT[M],ver[M],tot;void link(int u,int v,db w){ver[++tot]=v;NEXT[tot]=head[u];head[u]=tot;wei[tot]=w;}
const db EPS=1e-9;
inline int sign(db a){return a<-EPS?-1:a>EPS;}
inline int cmp(db a,db b){return sign(a-b);}
#define cross(p1,p2,p3) ((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y))
#define ocross(p1,p2,p3) sign(cross(p1,p2,p3))
struct P{
    db x,y;
    void add(db a,db b){
        x=a,y=b;
    }
    P(){}
    P(db _x,db _y) : x(_x), y(_y){}
    P operator+(P p){return {x+p.x,y+p.y};}
    P operator-(P p){return {x-p.x,y-p.y};}
    P operator*(db d){return{x*d,y*d};}
    P operator/(db d){return{x/d,y/d};}
    bool operator<(P p)const {
        int c=cmp(x,p.x);
        if(c) return c==-1;
        return cmp(y,p.y)==-1;
    }
    bool operator==(P o)const {
        return cmp(x,o.x)==0&&cmp(y,o.y)==0;
    }
};
bool chkLL(P p1,P p2,P q1,P q2){
    db a1=cross(q1,q2,p1);
    db a2=-cross(q1,q2,p2);
    return sign(a1+a2)!=0;
}
P isLL(P p1,P p2,P q1,P q2){
    db a1=cross(q1,q2,p1),a2=-cross(q1,q2,p2);
    return (p1*a2+p2*a1)/(a1+a2);
}
db dis(P p1,P p2){
    return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}
P p[11][10];
db xi[11],dist[500];
bool vis[500];
int n;
void dij(){
    memset(vis,false,sizeof(vis));
    for(int i=1;i<=4*(n+1)+1;i++) dist[i]=99999.0;
    dist[1]=0.0;
    priority_queue<pair<db,int> >q;
    q.push(make_pair(0,1));
    while(!q.empty()){
        int x=q.top().second;
        q.pop();
        if(vis[x]) continue;
        vis[x]=true;
        for(int i=head[x];i;i=NEXT[i]){
            int y=ver[i];
            if(dist[y]>dist[x]+wei[i]){
                dist[y]=dist[x]+wei[i];
                q.push(make_pair(-dist[y],y));
            }
        }
    }
    printf("%.2f\n",dist[(n+1)*4+1]);
}
int main(){
    //freopen("1.txt","r",stdin);
    db inp,in;
    while(~scanf("%d",&n)){
        if(n==-1) break;
        memset(head,0,sizeof(head));
        tot=0;
        for(int i=1;i<=n;i++){
            scanf("%lf",&inp);
            xi[i]=inp;
            p[i][0].add(inp,0.0);
            for(int j=1;j<=4;j++){
                scanf("%lf",&in);
                p[i][j].add(inp,in);
                //cout<<p[i][j].x<<' '<<p[i][j].y<<endl;
            }
            p[i][5].add(inp,10.0);
        }
        xi[0]=0;
        xi[n+1]=10;
        p[0][1].add(0.0,5.0);
        p[n+1][1].add(10.0,5.0);
        for(int i=0;i<=n+1;i++){
            for(int j=1;j<=n+1;j++){
                if(xi[i]>=xi[j]) continue;
                for(int ii=1;ii<=((i==0||i==n+1)?1:4);ii++){
                    for(int jj=1;jj<=((j==0||j==n+1)?1:4);jj++){
                        bool mark=true;
                        //cout<<i*4+ii<<' '<<j*4+jj<<endl;
                        for(int k=1;k<=n;k++){
                            if(xi[k]>xi[i]&&xi[k]<xi[j]){
                                for(int q=0;q<=4;q+=2){
                                    int res1=ocross(p[i][ii],p[j][jj],p[k][q]);
                                    int res2=ocross(p[i][ii],p[j][jj],p[k][q+1]);
                                    //cout<<res1<<' '<<res2<<endl;
                                    if(res1==-res2&&res1!=0)
                                        mark=false;
                                }
                            }
                        }
                        if(mark)
                            link(i*4+ii,j*4+jj,dis(p[i][ii],p[j][jj]));
                    }
                }
            }
        }
        dij();
    }
    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}

POJ 2653

题解:

依次在平面内放n个线段,问有在最上面线段的编号。

可以想到,一个线段被放进来只需跟最上面的线段比较,于是设定 q u e que que数组存储最上面的线段,每输入一个线段就 c h e c k check check这个线段与最上面的线段是否相交,交加则删除该线段即可。

代码:

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <ctime>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
#define PB push_back
#define MP make_pair
#define INF 1073741824
#define inf 1152921504606846976
#define pi 3.14159265358979323846
//#pragma comment(linker,"/STACK:10240000,10240000")
const int N=3e5+7,M=2e6;
const long long mod=1e9+7;
inline int read(){int ret=0;char ch=getchar();bool f=1;for(;!isdigit(ch);ch=getchar()) f^=!(ch^'-');for(;isdigit(ch);ch=getchar()) ret=(ret<<1)+(ret<<3)+ch-48;return f?ret:-ret;}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}//ÄæÔª
//int head[N],NEXT[N],ver[N],tot;void link(int u,int v){ver[++tot]=v;NEXT[tot]=head[u];head[u]=tot;}
const db EPS=1e-9;
inline int sign(db a){return a<-EPS?-1:a>EPS;}
inline int cmp(db a,db b){return sign(a-b);}
#define cross(p1,p2,p3) ((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y))
#define ocross(p1,p2,p3) sign(cross(p1,p2,p3))
struct P{
    db x,y;
    P(){}
    P(db _x,db _y) : x(_x), y(_y){}
    P operator+(P p){return {x+p.x,y+p.y};}
    P operator-(P p){return {x-p.x,y-p.y};}
    P operator*(db d){return{x*d,y*d};}
    P operator/(db d){return{x/d,y/d};}
    bool operator<(P p)const {
        int c=cmp(x,p.x);
        if(c) return c==-1;
        return cmp(y,p.y)==-1;
    }
    bool operator==(P o)const {
        return cmp(x,o.x)==0&&cmp(y,o.y)==0;
    }
};
bool chkLL(P p1,P p2,P q1,P q2){
    db a1=cross(q1,q2,p1);
    db a2=-cross(q1,q2,p2);
    return sign(a1+a2)!=0;
}
P isLL(P p1,P p2,P q1,P q2){
    db a1=cross(q1,q2,p1),a2=-cross(q1,q2,p2);
    return (p1*a2+p2*a1)/(a1+a2);
}
bool intersect(db l1,db r1,db l2,db r2){
    if(l1>r1) swap(l1,r1); if(l2>r2) swap(l2,r2);
    return !(cmp(r1,l2)==-1||cmp(r2,l1)==-1);
}
bool isSS(P p1,P p2,P q1,P q2){
    //cout<<ocross(p1,p2,q1)*ocross(p1,p2,q2)<<' '<<ocross(p1,p2,q1)*ocross(p1,p2,q2)<<endl;
    return intersect(p1.x,p2.x,q1.x,q2.x) && intersect(p1.y,p2.y,q1.y,q2.y) &&
    ocross(p1,p2,q1)*ocross(p1,p2,q2)<=0&&ocross(q1,q2,p1)*ocross(q1,q2,p2)<=0;
}
bool isSS_strict(P p1,P p2,P q1,P q2){
    return ocross(p1,p2,q1)*ocross(p1,p2,q2)<0&&ocross(q1,q2,p1)*ocross(q1,q2,p2)<0;
}
P p[N];
int ans[N];
int main(){
    //freopen("1.txt","r",stdin);
    int n;
    while(~scanf("%d",&n)){
        if(n==0) break;
        int tot=0;
        for(int i=0;i<2*n;i+=2){
            int ant=0;
            scanf("%lf%lf%lf%lf",&p[i].x,&p[i].y,&p[i+1].x,&p[i+1].y);
            for(int j=1;j<=tot;j++){
                //cout<<ans[j]<<' '<<ans[j]+1<<' '<<i<<' '<<i+1<<endl;
                if(isSS(p[ans[j]],p[ans[j]+1],p[i],p[i+1])){
                    continue;
                }
                ans[++ant]=ans[j];
            }
            ans[++ant]=i;
            tot=ant;
            //cout<<tot<<endl;
        }
        printf("Top sticks:");
        for(int i=1;i<=tot;i++){
            printf(" %d",ans[i]/2+1);
            if(i==tot) puts(".");
            else printf(",");
        }
    }
    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}

G POJ 1066

题解:

给定一张图,空白为房间,有线的是墙,每个墙壁的中间可以凿个门,问最少要凿几个门,才能逃出这个图

思路就是先找出交点,然后求出所有能凿出门的点。之后 O ( n 2 ) O(n^2) O(n2)地枚举点, c h e c k check check
这些点是否不与其他线段相交,若是则相连。折后只要跑一遍 b f s bfs bfs即可

代码:

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <ctime>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
#define PB push_back
#define MP make_pair
#define INF 1073741824
#define inf 1152921504606846976
#define pi 3.14159265358979323846
//#pragma comment(linker,"/STACK:10240000,10240000")
const int N=3e5+7,M=2e6;
const long long mod=1e9+7;
inline int read(){int ret=0;char ch=getchar();bool f=1;for(;!isdigit(ch);ch=getchar()) f^=!(ch^'-');for(;isdigit(ch);ch=getchar()) ret=(ret<<1)+(ret<<3)+ch-48;return f?ret:-ret;}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}//ÄæÔª
int head[N],NEXT[N],ver[N],tot;void link(int u,int v){ver[++tot]=v;NEXT[tot]=head[u];head[u]=tot;}
const db EPS=1e-9;
inline int sign(db a){return a<-EPS?-1:a>EPS;}
inline int cmp(db a,db b){return sign(a-b);}
#define cross(p1,p2,p3) ((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y))
#define ocross(p1,p2,p3) sign(cross(p1,p2,p3))
struct P{
    db x,y;
    void add(db xx,db yy){
        x=xx,y=yy;
    }
    P(){}
    P(db _x,db _y) : x(_x), y(_y){}
    P operator+(P p){return {x+p.x,y+p.y};}
    P operator-(P p){return {x-p.x,y-p.y};}
    P operator*(db d){return{x*d,y*d};}
    P operator/(db d){return{x/d,y/d};}
    bool operator<(P p)const {
        int c=cmp(x,p.x);
        if(c) return c==-1;
        return cmp(y,p.y)==-1;
    }
    bool operator==(P o)const {
        return cmp(x,o.x)==0&&cmp(y,o.y)==0;
    }
};
bool chkLL(P p1,P p2,P q1,P q2){
    db a1=cross(q1,q2,p1);
    db a2=-cross(q1,q2,p2);
    return sign(a1+a2)!=0;
}
P isLL(P p1,P p2,P q1,P q2){
    db a1=cross(q1,q2,p1),a2=-cross(q1,q2,p2);
    return (p1*a2+p2*a1)/(a1+a2);
}
bool intersect(db l1,db r1,db l2,db r2){
    if(l1>r1) swap(l1,r1); if(l2>r2) swap(l2,r2);
    return !(cmp(r1,l2)==-1|cmp(r2,l1)==-1);
}
bool isSS(P p1,P p2,P q1,P q2){
    return intersect(p1.x,p2.x,q1.x,q2.x) && intersect(p1.y,p2.y,q1.y,q2.y) &&
    ocross(p1,p2,q1)*ocross(p1,p2,q2)<=0&&ocross(q1,q2,p1)*ocross(q1,q2,p2)<=0;
}
bool isSS_strict(P p1,P p2,P q1,P q2){
    return ocross(p1,p2,q1)*ocross(p1,p2,q2)<0&&ocross(q1,q2,p1)*ocross(q1,q2,p2)<0;
}
P p[70];
P que[N],tmp[N];
bool mark[N];
int dis[N];
void bfs(){
    queue<int>q;
    q.push(0);
    dis[0]=1;
    while(!q.empty()){
        int x=q.front();
        q.pop();
        //cout<<x<<endl;
        if(mark[x]){
            printf("Number of doors = %d\n",dis[x]-1);
            return;
        }
        for(int i=head[x];i;i=NEXT[i]){
            int y=ver[i];
            if(dis[y]) continue;
            dis[y]=dis[x]+1;
            q.push(y);

        }

    }
}
int main(){
    //freopen("1.txt","r",stdin);
    int n;
    tot=0;
    scanf("%d",&n);
    for(int i=0;i<2*n;i+=2){
        scanf("%lf%lf%lf%lf",&p[i].x,&p[i].y,&p[i+1].x,&p[i+1].y);
    }
    scanf("%lf%lf",&que[0].x,&que[0].y);
    p[n*2].add(0.0,0.0);
    p[n*2+1].add(0.0,100.0);
    p[n*2+2].add(0.0,0.0);
    p[n*2+3].add(100.0,0.0);
    p[n*2+4].add(100.0,100.0);
    p[n*2+5].add(100.0,0.0);
    p[n*2+6].add(0.0,100.0);
    p[n*2+7].add(100.0,100.0);
    int ant=0;
    for(int i=0;i<2*n+8;i+=2){
        P pre,now,mi;
        pre.add(-1,-1);
        int pp=0;
        for(int j=0;j<2*n+8;j+=2){
            if(i==j) continue;
            if(isSS(p[i],p[i+1],p[j],p[j+1])){
                tmp[++pp]=isLL(p[i],p[i+1],p[j],p[j+1]);
            }
        }
        sort(tmp+1,tmp+1+pp);
        for(int j=2;j<=pp;j++){
            que[++ant]=(tmp[j]+tmp[j-1])/2.0;
            if(i>=2*n) mark[ant]=true;
            //cout<<"------"<<ant<<' '<<que[ant].x<<' '<<que[ant].y<<endl;
        }
    }
    //cout<<ant<<endl;
    for(int i=0;i<=ant;i++){
        for(int j=i+1;j<=ant;j++){
            bool flag=true;
            for(int k=0;k<2*n+8;k+=2){
                if(isSS_strict(que[i],que[j],p[k],p[k+1])){
                    //cout<<ocross(que[i],que[j],p[k])*ocross(que[i],que[j],p[k+1])<<' '<<ocross(p[k],p[k+1],que[i])*ocross(p[k],p[k+1],que[j])<<endl;
                    flag=false;
                    break;
                }
            }
            if(flag){
                link(i,j);
                link(j,i);
            }
        }
    }
    bfs();

    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}

H poj1410

套模板即可(注意的一点是他给的正方形的坐标是不一点就是原先顺序的左上右下以及判断的是线段而非直线)

代码:

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <ctime>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
#define PB push_back
#define MP make_pair
#define INF 1073741824
#define inf 1152921504606846976
#define pi 3.14159265358979323846
//#pragma comment(linker,"/STACK:10240000,10240000")
const int N=3e5+7,M=2e6;
const long long mod=1e9+7;
inline int read(){int ret=0;char ch=getchar();bool f=1;for(;!isdigit(ch);ch=getchar()) f^=!(ch^'-');for(;isdigit(ch);ch=getchar()) ret=(ret<<1)+(ret<<3)+ch-48;return f?ret:-ret;}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}//ÄæÔª
//int head[N],NEXT[N],ver[N],tot;void link(int u,int v){ver[++tot]=v;NEXT[tot]=head[u];head[u]=tot;}
const db EPS=1e-9;
inline int sign(db a){return a<-EPS?-1:a>EPS;}
inline int cmp(db a,db b){return sign(a-b);}
#define cross(p1,p2,p3) ((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y))
#define ocross(p1,p2,p3) sign(cross(p1,p2,p3))
struct P{
    db x,y;
    P(){}
    P(db _x,db _y) : x(_x), y(_y){}
    P operator+(P p){return {x+p.x,y+p.y};}
    P operator-(P p){return {x-p.x,y-p.y};}
    P operator*(db d){return{x*d,y*d};}
    P operator/(db d){return{x/d,y/d};}
    bool operator<(P p)const {
        int c=cmp(x,p.x);
        if(c) return c==-1;
        return cmp(y,p.y)==-1;
    }
    bool operator==(P o)const {
        return cmp(x,o.x)==0&&cmp(y,o.y)==0;
    }
};
bool chkLS(P p1,P p2,P q1,P q2){
    int a1=ocross(p1,p2,q1);
    int a2=ocross(p1,p2,q2);
    if(a1==0||a2==0) return true;
    if(a1==-a2) return true;
    return false;
}
bool chkLL(P p1,P p2,P q1,P q2){
    db a1=cross(q1,q2,p1);
    db a2=-cross(q1,q2,p2);
    return sign(a1+a2)!=0;
}
P isLL(P p1,P p2,P q1,P q2){
    db a1=cross(q1,q2,p1),a2=-cross(q1,q2,p2);
    return (p1*a2+p2*a1)/(a1+a2);
}
bool intersect(db l1,db r1,db l2,db r2){
    if(l1>r1) swap(l1,r1); if(l2>r2) swap(l2,r2);
    return !(cmp(r1,l2)==-1|cmp(r2,l1)==-1);
}
bool isSS(P p1,P p2,P q1,P q2){
    //cout<<ocross(p1,p2,q1)*ocross(p1,p2,q2)<<' '<<ocross(p1,p2,q1)*ocross(p1,p2,q2)<<endl;
    return intersect(p1.x,p2.x,q1.x,q2.x) && intersect(p1.y,p2.y,q1.y,q2.y) &&
    ocross(p1,p2,q1)*ocross(p1,p2,q2)<=0&&ocross(q1,q2,p1)*ocross(q1,q2,p2)<=0;
}
bool isSS_strict(P p1,P p2,P q1,P q2){
    return ocross(p1,p2,q1)*ocross(p1,p2,q2)<0&&ocross(q1,q2,p1)*ocross(q1,q2,p2)<0;
}
db Max(db x,db y){
    if(x<y) return y;
    return x;
}
db Min(db x,db y){
    if(x<y) return x;
    return y;
}
int main(){
    //freopen("1.txt","r",stdin);
    int n;
    db u,l,r,d;
    P p1,p2,p3,p4,p5,p6;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&p1.x,&p1.y,&p2.x,&p2.y,&l,&u,&r,&d);
        p3.x=Min(l,r);
        p3.y=Max(u,d);
        p6.x=Max(l,r);
        p6.y=Min(u,d);
        p4.x=p6.x,p4.y=p3.y;
        p5.x=p3.x,p5.y=p6.y;
        if(p1.x>=p3.x&&p1.x<=p4.x&&p1.y<=p3.y&&p1.y>=p5.y){
            puts("T");
            continue;
        }
        if(p2.x>=p3.x&&p2.x<=p4.x&&p2.y<=p3.y&&p2.y>=p5.y){
            puts("T");
            continue;
        }
        if(isSS(p1,p2,p3,p4)||isSS(p1,p2,p3,p5)||isSS(p1,p2,p4,p6)||isSS(p1,p2,p6,p5))
            puts("T");
        else
            puts("F");
    }

    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}

I POJ 1696

题解:

给定n个关键点,问一直不也右拐以及走过自己之前走过的路的蚂蚁的行走路线

可以发现每次走当前向左位置角度最小的方向距离最小的点即可。

也就是求sin cos dist这3个值的过程

代码:

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <ctime>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
#define PB push_back
#define MP make_pair
#define INF 1073741824
#define inf 1152921504606846976
#define pi 3.14159265358979323846
//#pragma comment(linker,"/STACK:10240000,10240000")
const int N=3e5+7,M=2e6;
const long long mod=1e9+7;
inline int read(){int ret=0;char ch=getchar();bool f=1;for(;!isdigit(ch);ch=getchar()) f^=!(ch^'-');for(;isdigit(ch);ch=getchar()) ret=(ret<<1)+(ret<<3)+ch-48;return f?ret:-ret;}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}//ÄæÔª
//int head[N],NEXT[N],ver[N],tot;void link(int u,int v){ver[++tot]=v;NEXT[tot]=head[u];head[u]=tot;}
const db EPS=1e-9;
inline int sign(db a){return a<-EPS?-1:a>EPS;}
inline int cmp(db a,db b){return sign(a-b);}
#define cross(p1,p2,p3) ((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y))
#define ocross(p1,p2,p3) sign(cross(p1,p2,p3))
struct P{
    db x,y;
    P(){}
    P(db _x,db _y) : x(_x), y(_y){}
    P operator+(P p){return {x+p.x,y+p.y};}
    P operator-(P p){return {x-p.x,y-p.y};}
    P operator*(db d){return{x*d,y*d};}
    P operator/(db d){return{x/d,y/d};}
    bool operator<(P p)const {
        int c=cmp(x,p.x);
        if(c) return c==-1;
        return cmp(y,p.y)==-1;
    }
    bool operator==(P o)const {
        return cmp(x,o.x)==0&&cmp(y,o.y)==0;
    }
};
bool chkLL(P p1,P p2,P q1,P q2){
    db a1=cross(q1,q2,p1);
    db a2=-cross(q1,q2,p2);
    return sign(a1+a2)!=0;
}
P isLL(P p1,P p2,P q1,P q2){
    db a1=cross(q1,q2,p1),a2=-cross(q1,q2,p2);
    return (p1*a2+p2*a1)/(a1+a2);
}
bool intersect(db l1,db r1,db l2,db r2){
    if(l1>r1) swap(l1,r1); if(l2>r2) swap(l2,r2);
    return !(cmp(r1,l2)==-1|cmp(r2,l1)==-1);
}
bool isSS(P p1,P p2,P q1,P q2){
    //cout<<ocross(p1,p2,q1)*ocross(p1,p2,q2)<<' '<<ocross(p1,p2,q1)*ocross(p1,p2,q2)<<endl;
    return intersect(p1.x,p2.x,q1.x,q2.x) && intersect(p1.y,p2.y,q1.y,q2.y) &&
    ocross(p1,p2,q1)*ocross(p1,p2,q2)<=0&&ocross(q1,q2,p1)*ocross(q1,q2,p2)<=0;
}
bool isSS_strict(P p1,P p2,P q1,P q2){
    return ocross(p1,p2,q1)*ocross(p1,p2,q2)<0&&ocross(q1,q2,p1)*ocross(q1,q2,p2)<0;
}
db Min(db x,db y){
    if(x<y) return x;
    return y;
}
db Abs(db x){
    if(x<0) return -x;
    return x;
}
db Max(db x,db y){
    if(x<y) return y;
    return x;
}
int main(){
    //freopen("1.txt","r",stdin);
    int t;
    P p1,p2,p3,p4,now,add;
    scanf("%d",&t);
    while(t--){
        scanf("%lf%lf%lf%lf",&p1.x,&p1.y,&p2.x,&p2.y);
        scanf("%lf%lf%lf%lf",&p3.x,&p3.y,&p4.x,&p4.y);
        if(p1.y<p2.y) swap(p1,p2);
        if(p3.y<p4.y) swap(p3,p4);
        if(isSS(p1,p2,p3,p4)){
            if(ocross(p1,p2,p3)==0&&ocross(p1,p2,p4)==0&&ocross(p3,p4,p1)==0&&ocross(p3,p4,p2)==0){
                puts("0.00");
                continue;
            }
            now=isLL(p1,p2,p3,p4);
            db h=Min(p1.y,p3.y)-now.y;
            if(sign(h)!=1){
                puts("0.00");
                continue;
            }
            int res1=cmp(p1.x,now.x);
            int res2=cmp(p3.x,now.x);
            if(p1.y<p3.y){
                add.x=p1.x+1.0;
                add.y=p1.y;
                add=isLL(p3,p4,p1,add);
                if(res1==-1&&res2==-1){
                    if(cmp(p1.x,add.x)!=1&&cmp(p1.x,p3.x)!=-1){
                        puts("0.00");
                        continue;
                    }
                }
                else if(res1==1&&res2==1){
                    if(cmp(p1.x,add.x)!=-1&&cmp(p1.x,p3.x)!=1){
                        puts("0.00");
                        continue;
                    }
                }
                printf("%.2f\n",h*Abs(add.x-p1.x)/2.0+EPS);
            }
            else {
                add.x=p3.x+1.0;
                add.y=p3.y;
                add=isLL(p1,p2,p3,add);
                if(res1==-1&&res2==-1){
                    if(cmp(p3.x,add.x)!=1&&cmp(p3.x,p1.x)!=-1){
                        puts("0.00");
                        continue;
                    }
                }
                else if(res1==1&&res2==1){
                    if(cmp(p3.x,add.x)!=-1&&cmp(p3.x,p1.x)!=1){
                        puts("0.00");
                        continue;
                    }
                }
                printf("%.2f\n",h*Abs(add.x-p3.x)/2.0+EPS);
            }
        }
        else puts("0.00");

    }

    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}

J POJ 3347

题解:

记录每个正方形中点的位置,每输入一个边长时看该正方形与前面已经确定的正方形紧挨着的时候的中心位置的最远值即是该正方形的位置。

代码:

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <ctime>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
#define PB push_back
#define MP make_pair
#define INF 1073741824
#define inf 1152921504606846976
#define pi 3.14159265358979323846
//#pragma comment(linker,"/STACK:10240000,10240000")
const int N=3e5+7,M=2e6;
const long long mod=1e9+7;
inline int read(){int ret=0;char ch=getchar();bool f=1;for(;!isdigit(ch);ch=getchar()) f^=!(ch^'-');for(;isdigit(ch);ch=getchar()) ret=(ret<<1)+(ret<<3)+ch-48;return f?ret:-ret;}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}//逆元
//int head[N],NEXT[N],ver[N],tot;void link(int u,int v){ver[++tot]=v;NEXT[tot]=head[u];head[u]=tot;}
const db EPS=1e-9;
inline int sign(db a){return a<-EPS?-1:a>EPS;}
inline int cmp(db a,db b){return sign(a-b);}
#define cross(p1,p2,p3) ((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y))
#define ocross(p1,p2,p3) sign(cross(p1,p2,p3))
struct P{
    db x,y;
    void add(db xx,db yy){
        x=xx,y=yy;
    }
    P(){}
    P(db _x,db _y) : x(_x), y(_y){}
    P operator+(P p){return {x+p.x,y+p.y};}
    P operator-(P p){return {x-p.x,y-p.y};}
    P operator*(db d){return{x*d,y*d};}
    P operator/(db d){return{x/d,y/d};}
    bool operator<(P p)const {
        int c=cmp(x,p.x);
        if(c) return c==-1;
        return cmp(y,p.y)==-1;
    }
    bool operator==(P o)const {
        return cmp(x,o.x)==0&&cmp(y,o.y)==0;
    }
};
bool chkLL(P p1,P p2,P q1,P q2){
    db a1=cross(q1,q2,p1);
    db a2=-cross(q1,q2,p2);
    return sign(a1+a2)!=0;
}
P isLL(P p1,P p2,P q1,P q2){
    db a1=cross(q1,q2,p1),a2=-cross(q1,q2,p2);
    return (p1*a2+p2*a1)/(a1+a2);
}
bool intersect(db l1,db r1,db l2,db r2){
    if(l1>r1) swap(l1,r1); if(l2>r2) swap(l2,r2);
    return !(cmp(r1,l2)==-1|cmp(r2,l1)==-1);
}
bool isSS(P p1,P p2,P q1,P q2){
    //cout<<ocross(p1,p2,q1)*ocross(p1,p2,q2)<<' '<<ocross(p1,p2,q1)*ocross(p1,p2,q2)<<endl;
    return intersect(p1.x,p2.x,q1.x,q2.x) && intersect(p1.y,p2.y,q1.y,q2.y) &&
    ocross(p1,p2,q1)*ocross(p1,p2,q2)<=0&&ocross(q1,q2,p1)*ocross(q1,q2,p2)<=0;
}
bool isSS_strict(P p1,P p2,P q1,P q2){
    return ocross(p1,p2,q1)*ocross(p1,p2,q2)<0&&ocross(q1,q2,p1)*ocross(q1,q2,p2)<0;
}
db dep(db a,db b,db c,db d){
    return a*c+b*d;
}
db det(db a,db b,db c,db d){
    return a*d-b*c;
}
int s[100],t[100],ans[100];
int n;
bool judge(int x){
    int l=s[x]-t[x],r=s[x]+t[x];
    for(int i=1;i<=n;i++){
        //cout<<i<<endl;
        if(i==x) continue;
        if(t[i]<t[x]) continue;
        //cout<<"-----"<<s[i]-t[i]<<' '<<s[i]+t[i]<<endl;
        if(l>=s[i]-t[i]&&l<=s[i]+t[i]){
            l=s[i]+t[i];
        }
        if(r>=s[i]-t[i]&&r<=s[i]+t[i]){
            r=s[i]-t[i];
        }
        //cout<<l<<endl;
        //cout<<r<<endl;
    }
    if(l>=r) return false;
    return true;
}
int main(){
    //freopen("1.txt","r",stdin);
    int inp;
    while(~scanf("%d",&n)){
        if(n==0) break;
        int r=0,zj;
        for(int i=1;i<=n;i++){
            scanf("%d",&inp);
            t[i]=inp;
            int res=0;
            bool mark=false;
            for(int j=i-1;j>=1;j--){
                if(inp<=t[j]){
                    res=max(2*inp+s[j],res);
                }
                else {
                    res=max(2*t[j]+s[j],res);
                }
            }
            res=max(res,t[i]);
            s[i]=res;
            //r=max(s[i]+t[i]*2,r);
        }
        int ant=0;
        for(int i=1;i<=n;i++){
            //cout<<s[i]<<' '<<t[i]<<endl;
            if(judge(i)) ans[++ant]=i;
        }
        for(int i=1;i<=ant;i++){
            printf("%d",ans[i]);
            if(i==ant) puts("");
            else printf(" ");
        }
    }

    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}

POJ 2826

题解:

给定2条线段求从上到下被雨淋到的最大面积。

分类讨论

  1. 线段不相交 答案是0.00
  2. 线段之间有重合部分 答案是0.00
  3. 存在一条线段的最高点的y与交点的y相等 答案是0.00
  4. 两个高点在交点的同侧,且最高点的x距离交点的x最远 答案是0.00
  5. 其他正常求

代码:

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <ctime>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
#define PB push_back
#define MP make_pair
#define INF 1073741824
#define inf 1152921504606846976
#define pi 3.14159265358979323846
//#pragma comment(linker,"/STACK:10240000,10240000")
const int N=3e5+7,M=2e6;
const long long mod=1e9+7;
inline int read(){int ret=0;char ch=getchar();bool f=1;for(;!isdigit(ch);ch=getchar()) f^=!(ch^'-');for(;isdigit(ch);ch=getchar()) ret=(ret<<1)+(ret<<3)+ch-48;return f?ret:-ret;}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}//ÄæÔª
//int head[N],NEXT[N],ver[N],tot;void link(int u,int v){ver[++tot]=v;NEXT[tot]=head[u];head[u]=tot;}
const db EPS=1e-9;
inline int sign(db a){return a<-EPS?-1:a>EPS;}
inline int cmp(db a,db b){return sign(a-b);}
#define cross(p1,p2,p3) ((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y))
#define ocross(p1,p2,p3) sign(cross(p1,p2,p3))
struct P{
    db x,y;
    P(){}
    P(db _x,db _y) : x(_x), y(_y){}
    P operator+(P p){return {x+p.x,y+p.y};}
    P operator-(P p){return {x-p.x,y-p.y};}
    P operator*(db d){return{x*d,y*d};}
    P operator/(db d){return{x/d,y/d};}
    bool operator<(P p)const {
        int c=cmp(x,p.x);
        if(c) return c==-1;
        return cmp(y,p.y)==-1;
    }
    bool operator==(P o)const {
        return cmp(x,o.x)==0&&cmp(y,o.y)==0;
    }
};
bool chkLL(P p1,P p2,P q1,P q2){
    db a1=cross(q1,q2,p1);
    db a2=-cross(q1,q2,p2);
    return sign(a1+a2)!=0;
}
P isLL(P p1,P p2,P q1,P q2){
    db a1=cross(q1,q2,p1),a2=-cross(q1,q2,p2);
    return (p1*a2+p2*a1)/(a1+a2);
}
bool intersect(db l1,db r1,db l2,db r2){
    if(l1>r1) swap(l1,r1); if(l2>r2) swap(l2,r2);
    return !(cmp(r1,l2)==-1|cmp(r2,l1)==-1);
}
bool isSS(P p1,P p2,P q1,P q2){
    //cout<<ocross(p1,p2,q1)*ocross(p1,p2,q2)<<' '<<ocross(p1,p2,q1)*ocross(p1,p2,q2)<<endl;
    return intersect(p1.x,p2.x,q1.x,q2.x) && intersect(p1.y,p2.y,q1.y,q2.y) &&
    ocross(p1,p2,q1)*ocross(p1,p2,q2)<=0&&ocross(q1,q2,p1)*ocross(q1,q2,p2)<=0;
}
bool isSS_strict(P p1,P p2,P q1,P q2){
    return ocross(p1,p2,q1)*ocross(p1,p2,q2)<0&&ocross(q1,q2,p1)*ocross(q1,q2,p2)<0;
}
db Min(db x,db y){
    if(x<y) return x;
    return y;
}
db Abs(db x){
    if(x<0) return -x;
    return x;
}
db Max(db x,db y){
    if(x<y) return y;
    return x;
}
int main(){
    //freopen("1.txt","r",stdin);
    int t;
    P p1,p2,p3,p4,now,add;
    scanf("%d",&t);
    while(t--){
        scanf("%lf%lf%lf%lf",&p1.x,&p1.y,&p2.x,&p2.y);
        scanf("%lf%lf%lf%lf",&p3.x,&p3.y,&p4.x,&p4.y);
        if(p1.y<p2.y) swap(p1,p2);
        if(p3.y<p4.y) swap(p3,p4);
        if(isSS(p1,p2,p3,p4)){
            if(ocross(p1,p2,p3)==0&&ocross(p1,p2,p4)==0&&ocross(p3,p4,p1)==0&&ocross(p3,p4,p2)==0){
                puts("0.00");
                continue;
            }
            now=isLL(p1,p2,p3,p4);
            db h=Min(p1.y,p3.y)-now.y;
            if(sign(h)!=1){
                puts("0.00");
                continue;
            }
            int res1=cmp(p1.x,now.x);
            int res2=cmp(p3.x,now.x);
            if(p1.y<p3.y){
                add.x=p1.x+1.0;
                add.y=p1.y;
                add=isLL(p3,p4,p1,add);
                if(res1==-1&&res2==-1){
                    if(cmp(p1.x,add.x)!=1&&cmp(p1.x,p3.x)!=-1){
                        puts("0.00");
                        continue;
                    }
                }
                else if(res1==1&&res2==1){
                    if(cmp(p1.x,add.x)!=-1&&cmp(p1.x,p3.x)!=1){
                        puts("0.00");
                        continue;
                    }
                }
                printf("%.2f\n",h*Abs(add.x-p1.x)/2.0+EPS);
            }
            else {
                add.x=p3.x+1.0;
                add.y=p3.y;
                add=isLL(p1,p2,p3,add);
                if(res1==-1&&res2==-1){
                    if(cmp(p3.x,add.x)!=1&&cmp(p3.x,p1.x)!=-1){
                        puts("0.00");
                        continue;
                    }
                }
                else if(res1==1&&res2==1){
                    if(cmp(p3.x,add.x)!=-1&&cmp(p3.x,p1.x)!=1){
                        puts("0.00");
                        continue;
                    }
                }
                printf("%.2f\n",h*Abs(add.x-p3.x)/2.0+EPS);
            }
        }
        else puts("0.00");

    }

    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}

L POJ 1039

题解:

枚举2个端点相连,判断是否所有上顶点都在直线上侧,下顶点都在直线下侧。
(注意答案是x轴的最大值,不是距离)

代码:

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <ctime>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
#define PB push_back
#define MP make_pair
#define INF 1073741824
#define inf 1152921504606846976
#define pi 3.14159265358979323846
//#pragma comment(linker,"/STACK:10240000,10240000")
const int N=3e5+7,M=2e6;
const long long mod=1e9+7;
inline int read(){int ret=0;char ch=getchar();bool f=1;for(;!isdigit(ch);ch=getchar()) f^=!(ch^'-');for(;isdigit(ch);ch=getchar()) ret=(ret<<1)+(ret<<3)+ch-48;return f?ret:-ret;}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}//ÄæÔª
//int head[N],NEXT[N],ver[N],tot;void link(int u,int v){ver[++tot]=v;NEXT[tot]=head[u];head[u]=tot;}
const db EPS=1e-9;
inline int sign(db a){return a<-EPS?-1:a>EPS;}
inline int cmp(db a,db b){return sign(a-b);}
#define cross(p1,p2,p3) ((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y))
#define ocross(p1,p2,p3) sign(cross(p1,p2,p3))
struct P{
    db x,y;
    void add(db xx,db yy){
        x=xx,y=yy;
    }
    P(){}
    P(db _x,db _y) : x(_x), y(_y){}
    P operator+(P p){return {x+p.x,y+p.y};}
    P operator-(P p){return {x-p.x,y-p.y};}
    P operator*(db d){return{x*d,y*d};}
    P operator/(db d){return{x/d,y/d};}
    bool operator<(P p)const {
        int c=cmp(x,p.x);
        if(c) return c==-1;
        return cmp(y,p.y)==-1;
    }
    bool operator==(P o)const {
        return cmp(x,o.x)==0&&cmp(y,o.y)==0;
    }
};
bool chkLL(P p1,P p2,P q1,P q2){
    db a1=cross(q1,q2,p1);
    db a2=-cross(q1,q2,p2);
    return sign(a1+a2)!=0;
}
P isLL(P p1,P p2,P q1,P q2){
    db a1=cross(q1,q2,p1),a2=-cross(q1,q2,p2);
    return (p1*a2+p2*a1)/(a1+a2);
}
bool intersect(db l1,db r1,db l2,db r2){
    if(l1>r1) swap(l1,r1); if(l2>r2) swap(l2,r2);
    return !(cmp(r1,l2)==-1|cmp(r2,l1)==-1);
}
bool isSS(P p1,P p2,P q1,P q2){
    //cout<<ocross(p1,p2,q1)*ocross(p1,p2,q2)<<' '<<ocross(p1,p2,q1)*ocross(p1,p2,q2)<<endl;
    return intersect(p1.x,p2.x,q1.x,q2.x) && intersect(p1.y,p2.y,q1.y,q2.y) &&
    ocross(p1,p2,q1)*ocross(p1,p2,q2)<=0&&ocross(q1,q2,p1)*ocross(q1,q2,p2)<=0;
}
bool isSS_strict(P p1,P p2,P q1,P q2){
    return ocross(p1,p2,q1)*ocross(p1,p2,q2)<0&&ocross(q1,q2,p1)*ocross(q1,q2,p2)<0;
}
bool isSS_ch(P p1,P p2,P q1,P q2){
    return ocross(p1,p2,q1)==0&&ocross(p1,p2,q2)==0&&ocross(q1,q2,p1)==0&&ocross(q1,q2,p2)==0;
}
db dep(db a,db b,db c,db d){
    return a*c+b*d;
}
db det(db a,db b,db c,db d){
    return a*d-b*c;
}
P p[30],pp[30],now;
db res;
int n;
bool mark;
bool solve(P p1,P p2,int zi){
    for(int i=1;i<=zi;i++){
        //cout<<ocross(p1,p2,p[i])<<' '<<ocross(p1,p2,pp[i])<<' '<<zi<<' '<<i<<endl;
        //cout<<pp[i].x<<' '<<pp[i].y<<"-------"<<' '<<p2.x<<' '<<p2.y<<endl;
        if(ocross(p1,p2,p[i])==-1||ocross(p1,p2,pp[i])==1) return false;
    }
    return true;
}
void find_(P p1,P p2,int zi){
    int zz=0;
    //cout<<zi<<endl;
    //cout<<p2.y<<endl;
    for(int i=zi+1;i<=n;i++){
        //cout<<ocross(p1,p2,p[i])<<' '<<ocross(p1,p2,pp[i])<<' '<<zi<<' '<<i<<endl;
        if(ocross(p1,p2,p[i])==-1) {
            zz=i;
            break;
        }
        if(ocross(p1,p2,pp[i])==1) {
            zz=-i;
            break;
        }
    }
    if(zz==0) mark=true;
    else {
        if(zz>0){
            now=isLL(p1,p2,p[zz],p[zz-1]);
            if(cmp(res,now.x)==-1) res=now.x;
        }
        else {
            zz=-zz;
            now=isLL(p1,p2,pp[zz],pp[zz-1]);
            if(cmp(res,now.x)==-1) res=now.x;
        }
    }
}
int main(){
    //cout<<det(7.0-0.0,-6.57-1.0,5.0,-4.45-1.0)<<endl;
    //freopen("1.txt","r",stdin);
    while(~scanf("%d",&n)){
        if(n==0) break;
        res=-20000000.0;
        mark=false;
        for(int i=1;i<=n;i++){
            scanf("%lf%lf",&p[i].x,&p[i].y);
            pp[i].add(p[i].x,p[i].y-1.0);
        }
        for(int i=1;i<=n;i++){
            for(int j=i+1;j<=n;j++){
                if(solve(p[i],p[j],j)){
                    find_(p[i],p[j],j);
                }
                if(solve(p[i],pp[j],j)){
                    find_(p[i],pp[j],j);
                }
                if(solve(pp[i],p[j],j)){
                    find_(pp[i],p[j],j);
                }
                if(solve(pp[i],pp[j],j)){
                    find_(pp[i],pp[j],j);
                }
            }
        }
        if(mark) puts("Through all the pipe.");
        else printf("%.2f\n",res);
    }

    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值