Training:计算几何基础

计算几何基础部分大部分题目只要有模板就能过了,下面的题也大都是贴模板过的。

HDU 1086:
http://acm.hust.edu.cn/vjudge/problem/visitOriginUrl.action?id=17612
给出 n 条线段,求其中相交的对数。

#include<cstdio>
struct Line{
    double x1,y1,x2,y2;
}a[110];
bool solve(Line a,Line b){
    if(((a.x1-b.x1)*(a.y2-b.y1)-(a.x2-b.x1)*(a.y1-b.y1))*((a.x1-b.x2)*(a.y2-b.y2)-(a.x2-b.x2)*(a.y1-b.y2))>0)return false;
    if(((b.x1-a.x1)*(b.y2-a.y1)-(b.x2-a.x1)*(b.y1-a.y1))*((b.x1-a.x2)*(b.y2-a.y2)-(b.x2-a.x2)*(b.y1-a.y2))>0)return false;
    return true;
}
int main(){
    int n;
    while(~scanf("%d",&n)&&n){
        int cnt=0;
        for(int i=0;i<n;++i)
            scanf("%lf%lf%lf%lf",&a[i].x1,&a[i].y1,&a[i].x2,&a[i].y2);
        for(int i=0;i<n;++i)
            for(int j=i+1;j<n;++j)
                if(solve(a[i],a[j]))
                    ++cnt;
        printf("%d\n",cnt);
    }
    return 0;
}

HDU 1115:
http://acm.hust.edu.cn/vjudge/problem/visitOriginUrl.action?id=16214
按顺序给出多个点,求给出点的的重心坐标。

#include<cstdio>
using namespace std;
const int maxn=1000010;
struct node{
    double x,y;
}a[maxn];
node gravity(node *p, int n)
{
    double area = 0;
    node center;
    center.x = 0;
    center.y = 0;
    for (int i = 0; i < n-1; i++)
    {
        area += (p[i].x*p[i+1].y - p[i+1].x*p[i].y)/2;
        center.x += (p[i].x*p[i+1].y - p[i+1].x*p[i].y) * (p[i].x + p[i+1].x);
        center.y += (p[i].x*p[i+1].y - p[i+1].x*p[i].y) * (p[i].y + p[i+1].y);
    }
    area += (p[n-1].x*p[0].y - p[0].x*p[n-1].y)/2;
    center.x += (p[n-1].x*p[0].y - p[0].x*p[n-1].y) * (p[n-1].x + p[0].x);
    center.y += (p[n-1].x*p[0].y - p[0].x*p[n-1].y) * (p[n-1].y + p[0].y);
    center.x /= 6*area;
    center.y /= 6*area;
    return center;
}
int main(){
    int t;scanf("%d",&t);
    while(t--){
        int n;scanf("%d",&n);
        for(int i=0;i<n;++i)
            scanf("%lf%lf",&a[i].x,&a[i].y);
        node ans=gravity(a,n);
        printf("%.2lf %.2lf\n",ans.x,ans.y);
    }
    return 0;
}

HDU 2036:
http://acm.hust.edu.cn/vjudge/problem/visitOriginUrl.action?id=17490
按顺序给出多个点的坐标,求所构成的凸多边形面积。

#include<cstdio>
#include<cmath>
const int maxn=110;
struct point{
    double x,y;
}a[maxn];
double area_polygon(int n,point* p){
    double s1=0,s2=0;
    for(int i=0;i<n;++i)
        s1+=p[(i+1)%n].y*p[i].x,s2+=p[(i+1)%n].y*p[(i+2)%n].x;
    return fabs(s1-s2)/2;
}
int main(){
    int n;
    while(~scanf("%d",&n)&&n){
        for(int i=0;i<n;++i)
            scanf("%lf%lf",&a[i].x,&a[i].y);
        printf("%.1lf\n",area_polygon(n,a));
    }
    return 0;
}

HDU 2108:
http://acm.hust.edu.cn/vjudge/problem/visitOriginUrl.action?id=18631
按顺序给出多个点,判断形成的是凸多边形,还是凹多边形。

#include<cstdio>
#include<cmath>
const int maxn=110;
struct point{
    double x,y;
}a[maxn];
#define eps 1e-8
#define _sign(x) ((x)>eps?1:((x)<-eps?2:0))
double xmult(point p1,point p2,point p0){
    return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
int is_convex(int n,point* p){
    int i,s[3]={1,1,1};
    for (i=0;i<n&&s[1]|s[2];i++)
        s[_sign(xmult(p[(i+1)%n],p[(i+2)%n],p[i]))]=0; return s[1]|s[2];
}
int main(){
    int n;
    while(~scanf("%d",&n)&&n){
        for(int i=0;i<n;++i)
            scanf("%lf%lf",&a[i].x,&a[i].y);
        puts(is_convex(n,a)?"convex":"concave");
    }
    return 0;
}

HDU 1392:
http://acm.hust.edu.cn/vjudge/problem/visitOriginUrl.action?id=18630
给出多个点,求凸包的周长。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=110;
struct point{
    double x,y;
}a[maxn],b[maxn];
bool mult(point p0,point p1,point p2){
    return (p1.x-p0.x)*(p2.y-p0.y)>=(p2.x-p0.x)*(p1.y-p0.y);
}
bool operator<(const point &p1,const point &p2){
    return p1.y<p2.y||(p1.y==p2.y&&p1.x<p2.x);
}
int graham(point pnt[],int n,point res[]){
    int i,len,top=1;
    sort(pnt,pnt+n);
    if(n==0) return 0;
    res[0]=pnt[0];
    if(n==1) return 1;
    res[1]=pnt[1];
    if(n==2) return 2;
    res[2]=pnt[2];
    for(i=2;i<n;i++){
        while(top&&mult(pnt[i],res[top],res[top-1]))
            top--;
        res[++top]=pnt[i];
    }
    len=top;res[++top]=pnt[n-2];
    for(i=n-3;i>=0;i--){
        while(top!=len&&mult(pnt[i],res[top],res[top-1]))
            top--;
        res[++top]=pnt[i];
    }
    return top;
}
int main(){
    int n;
    while(~scanf("%d",&n)&&n){
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        for(int i=0;i<n;++i) scanf("%lf%lf",&a[i].x,&a[i].y);
        int k=graham(a,n,b);
        double ans=0;
        for(int i=0;i<k-1;++i)
            ans+=sqrt((b[i].x-b[i+1].x)*(b[i].x-b[i+1].x)+(b[i].y-b[i+1].y)*(b[i].y-b[i+1].y));
        if(k>2) ans+=sqrt((b[k-1].x-b[0].x)*(b[k-1].x-b[0].x)+(b[k-1].y-b[0].y)*(b[k-1].y-b[0].y));
        printf("%.2lf\n",ans);
    }
    return 0;
}

HDU 1348:
http://acm.hust.edu.cn/vjudge/problem/visitOriginUrl.action?id=32007
求凸包每个顶点向外延伸半径为1的圆后所得图形的周长。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=1010;
struct point{
    double x,y;
}a[maxn],b[maxn];
bool mult(point p0,point p1,point p2){
    return (p1.x-p0.x)*(p2.y-p0.y)>=(p2.x-p0.x)*(p1.y-p0.y);
}
bool operator<(const point &p1,const point &p2){
    return p1.y<p2.y||(p1.y==p2.y&&p1.x<p2.x);
}
int graham(point pnt[],int n,point res[]){
    int i,len,top=1;
    sort(pnt,pnt+n);
    if(n==0) return 0;
    res[0]=pnt[0];
    if(n==1) return 1;
    res[1]=pnt[1];
    if(n==2) return 2;
    res[2]=pnt[2];
    for(i=2;i<n;i++){
        while(top&&mult(pnt[i],res[top],res[top-1]))
            top--;
        res[++top]=pnt[i];
    }
    len=top;res[++top]=pnt[n-2];
    for(i=n-3;i>=0;i--){
        while(top!=len&&mult(pnt[i],res[top],res[top-1]))
            top--;
        res[++top]=pnt[i];
    }
    return top;
}
int main(){
    int t;scanf("%d",&t);
    while(t--){
        int n,l;scanf("%d%d",&n,&l);
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        for(int i=0;i<n;++i) scanf("%lf%lf",&a[i].x,&a[i].y);
        int k=graham(a,n,b);
        double ans=0;
        for(int i=0;i<k-1;++i)
            ans+=sqrt((b[i].x-b[i+1].x)*(b[i].x-b[i+1].x)+(b[i].y-b[i+1].y)*(b[i].y-b[i+1].y));
        if(k>2) ans+=sqrt((b[k-1].x-b[0].x)*(b[k-1].x-b[0].x)+(b[k-1].y-b[0].y)*(b[k-1].y-b[0].y));
        ans+=2*acos(-1)*l;
        printf("%.0lf\n",ans);
        if(t) printf("\n");
    }
    return 0;
}

HDU 2150:
http://acm.hust.edu.cn/vjudge/problem/visitOriginUrl.action?id=31178
给出多条线段,判断有无相交线段。

#include<cstdio>
struct Line{
    double x1,y1,x2,y2;
    Line(double x1=0,double y1=0,double x2=0,double y2=0):x1(x1),y1(y1),x2(x2),y2(y2){}
};
struct node{
    int k;
    Line l[110];
}a[33];
bool solve(Line a,Line b){
    if(((a.x1-b.x1)*(a.y2-b.y1)-(a.x2-b.x1)*(a.y1-b.y1))*((a.x1-b.x2)*(a.y2-b.y2)-(a.x2-b.x2)*(a.y1-b.y2))>0)return false;
    if(((b.x1-a.x1)*(b.y2-a.y1)-(b.x2-a.x1)*(b.y1-a.y1))*((b.x1-a.x2)*(b.y2-a.y2)-(b.x2-a.x2)*(b.y1-a.y2))>0)return false;
    return true;
}
int main(){
    int n;
    while(~scanf("%d",&n)){
        for(int i=0;i<n;++i){
            scanf("%d",&a[i].k);
            --a[i].k;
            double px1,py1;
            scanf("%lf%lf",&px1,&py1);
            for(int j=0;j<a[i].k;++j){
                double x1,y1;
                scanf("%lf%lf",&x1,&y1);
                a[i].l[j]=Line(px1,py1,x1,y1);
                px1=x1,py1=y1;
            }
        }
        bool flag=false;
        for(int i=0;i<n;++i)
            for(int j=i+1;j<n;++j)
                for(int k=0;k<a[i].k;++k)
                    for(int l=0;l<a[j].k;++l)
                        if(solve(a[i].l[k],a[j].l[l])) {flag=true;goto END;}
    END:
        printf("%s\n",flag?"Yes":"No");
    }
    return 0;
}

HDU 1558:
http://acm.hust.edu.cn/vjudge/problem/visitOriginUrl.action?id=19356
给出多条线段,输出有几个连通块。判断线段相交之后,用并查集求解。

#include<iostream>
#include<string>
using namespace std;
const int maxn=1010;
int p[maxn],num[maxn];
struct Line{
    double x1,y1,x2,y2;
    Line(double x1=0,double y1=0,double x2=0,double y2=0):x1(x1),y1(y1),x2(x2),y2(y2){}
}a[maxn];
//有模板就是好!!!
bool solve(Line a,Line b){
    if(((a.x1-b.x1)*(a.y2-b.y1)-(a.x2-b.x1)*(a.y1-b.y1))*((a.x1-b.x2)*(a.y2-b.y2)-(a.x2-b.x2)*(a.y1-b.y2))>0)return false;
    if(((b.x1-a.x1)*(b.y2-a.y1)-(b.x2-a.x1)*(b.y1-a.y1))*((b.x1-a.x2)*(b.y2-a.y2)-(b.x2-a.x2)*(b.y1-a.y2))>0)return false;
    return true;
}
int find(int x){
    return p[x]==x?x:p[x]=find(p[x]);
}
void merge(int x,int y){
    int fx=find(x),fy=find(y);
    if(fx!=fy) p[fx]=fy,num[fy]+=num[fx];
    return;
}
int main(){
    int t;cin>>t;
    while(t--){
        int n,cnt=0;cin>>n;
        for(int i=0;i<n;++i){
            string s;cin>>s;
            if(s=="P"){
                ++cnt,p[cnt]=cnt,num[cnt]=1;
                Line& k=a[cnt];
                cin>>k.x1>>k.y1>>k.x2>>k.y2;
                for(int j=1;j<cnt;++j){
                    if(find(j)!=find(cnt)&&solve(a[j],k))
                        merge(cnt,j);
                }
            }
            else if(s=="Q"){
                int k;cin>>k;
                cout<<num[find(k)]<<endl;
            }
        }
        if(t) cout<<endl;
    }
    return 0;
}

HDU 1785:
http://acm.hust.edu.cn/vjudge/problem/visitOriginUrl.action?id=30271
就是结构体重载运算符的题。

#include<cstdio>
#include<algorithm>
const int maxn=110;
struct node{
    double x,y;
    bool operator < (const node& rhs) const {
        return x*rhs.y>rhs.x*y;
    }
}a[maxn];
int main(){
    int n;
    while(~scanf("%d",&n)&&n>=0){
        for(int i=0;i<n;++i) scanf("%lf%lf",&a[i].x,&a[i].y);
        std::sort(a,a+n);
        for(int i=0;i<n;++i) printf("%.1lf %.1lf%c",a[i].x,a[i].y,i==n-1?'\n':' ');
    }
    return 0;
}

你可能感兴趣的:(ACM,HDU,计算几何)