题解:蓝书习题·第4章·几何问题

计算几何模板

Coord getCoord()
{
    double x,y;
    return scanf("%lf%lf",&x,&y),Coord(x,y);
}

Triangle Fun UVA - 11437

按照题目意思的直接解法。

int main()
{
    int n;
    for(scanf("%d",&n); n--;)
    {
        Coord A=getCoord(),B=getCoord(),C=getCoord(),
              D=B+(C-B)/3.0,E=C+(A-C)/3.0,F=A+(B-A)/3.0,
              P=getLineIntersection(A,D,B,E),
              Q=getLineIntersection(B,E,C,F),
              R=getLineIntersection(C,F,A,D);
        printf("%.0f\n",fabs(Area2(P,Q,R)/2));
    }
}

可证明△ABC的面积是△PQR的7倍,于是有下面的解法。

int main()
{
    int n;
    for(scanf("%d",&n);
            n--;
            printf("%.0f\n",
                   fabs(Area2(getCoord(),getCoord(),getCoord())/14)));
}

Determine the Shape UVA - 11800

int main()
{
    char s[6][32]=
    {
        "Square",
        "Rectangle",
        "Rhombus",
        "Parallelogram",
        "Trapezium",
        "Ordinary Quadrilateral"
    };
    int t,kase=0,ans;
    for(scanf("%d",&t); t--; printf("Case %d: %s\n",++kase,s[ans]))
    {
        ans=5;
        Coord p[4]= {getCoord(),getCoord(),getCoord(),getCoord()};
        sort(p,p+4,cmpCoord);
        do
        {
            Coord &a=p[0],&b=p[1],&c=p[2],&d=p[3];
            if(!sgn(Cross(b-a,d-c))||!sgn(Cross(a-d,c-b)))ans=min(ans,4);
            if(!sgn(Cross(b-a,d-c))&&!sgn(Cross(a-d,c-b)))
            {
                ans=min(ans,sgn(Dot(c-a,b-d))?3:2);
                if(!sgn(Dot(b-a,c-b)))
                    ans=min(ans,sgn(Dot(c-a,b-d))?1:0);
            }
        }
        while(next_permutation(p,p+4,cmpCoord));
    }
}

Athletics Track UVA - 11646

int main()
{
    for(double a,b,c,kase=0;
            ~scanf("%lf : %lf",&a,&b);
            printf("Case %.0f: %.5f %.5f\n",kase+=1,a*c,b*c))
        c=200/(sqrt(a*a+b*b)*atan(b/a)+a);
}

Tunnelling the Earth UVA - 11817

int main()
{
    int n;
    double a[4],d,r=6371009,PI=acos(-1);
    for(scanf("%d",&n); n--; printf("%.0lf\n",2*r*asin(d/r/2)-d))
    {
        for(int i=0; i!=4; ++i)
        {
            scanf("%lf",&a[i]);
            a[i]*=PI/180;
        }
        d=r*sqrt(2-2*(cos(a[0])*cos(a[2])*cos(a[1]-a[3])+sin(a[0])*sin(a[2])));
    }
}

Morley’s Theorem UVA - 11178

int main()
{
    int t;
    for(scanf("%d",&t); t--; printf("\n"))
    {
        Coord A=getCoord(),B=getCoord(),C=getCoord(),D;
        for(int i=0; i!=3; ++i)
        {
            double b=Angle(A-B,C-B),c=Angle(A-C,B-C);
            Line BD(B,Rotate(C-B,b/3)),CD(C,Rotate(B-C,-c/3));
            D=getLineIntersection(BD,CD);
            printf("%.6f %.6f ",D.X,D.Y);
            swap(A,B),swap(B,C);
        }
    }
}

That Nice Euler Circuit UVALive - 3263

struct CoordCmp
{
    bool operator()(Coord A,Coord B)
    {
        return cmpCoord(A,B);
    }
};
int main()
{
    for(int e,kase=0; scanf("%d",&e)&&e; printf("Case %d: There are %d pieces.\n",++kase,--e))//读入时e本身大1个(最后一笔回到起点),因此上面得到的边数要减去一个
    {
        vector<Coord> p;
        set<Coord,CoordCmp> v;
        for(int i=0; i<e; ++i)
        {
            p.push_back(getCoord());
            v.insert(p.back());
            for(int j=1; j<i; ++j)
                if(SegmentProperIntersection(p[i-1],p[i],p[j-1],p[j]))//不包含端点的相交 
                    v.insert(getLineIntersection(p[i-1],p[i],p[j-1],p[j]));
        }
        for(set<Coord,CoordCmp>::iterator i=v.begin(); i!=v.end(); ++i)
            for(int j=1; j<p.size(); ++j)
                if(onSegment(*i,p[j-1],p[j]))
                    ++e;
        e+=2-v.size();//欧拉定理:平面图的点数V、边数E和面数F满足F=E+2-V
    }
}

Dog Distance UVA - 11796

int main()
{
    int I,kase=0,a[2];
    double maxd,mind,t,len[2];
    Coord p[2];
    vector<Coord> q[2];
    for(scanf("%d",&I); I--; printf("Case %d: %.0f\n",++kase,maxd-mind))
    {
        scanf("%d%d",&a[0],&a[1]);
        for(int i=0; i<2; ++i)
        {
            while(a[i]--)q[i].push_back(getCoord());
            for(int j=len[i]=0; j+1<q[i].size(); ++j)
                len[i]+=abs(q[i][j]-q[i][j+1]);
            p[i]=q[i].back(),q[i].pop_back();
        }
        for(maxd=mind=abs(p[0]-p[1]); !q[0].empty()&&!q[1].empty();)
        {
            Coord v[2]= {q[0].back()-p[0],q[1].back()-p[1]};
            t=min(abs(v[0])/len[0],abs(v[1])/len[1]);
            for(int i=0; i<2; ++i)
                if(q[i].back()==(p[i]+=v[i]*=t*len[i]/abs(v[i])))
                    q[i].pop_back();
            maxd=max(maxd,abs(p[0]-p[1]));
            mind=min(mind,DistanceToSegment(p[0],p[1]-v[1]+v[0],p[1]));
        }
    }
}

2D Geometry 110 in 1! UVA - 12304

EPS调成1e-6,再小判定圆和直线相切受影响。

double getd()
{
    double x;
    return scanf("%lf",&x),x;
}
Coord getCoord()
{
    double x=getd(),y=getd();
    return Coord(x,y);
}
void printf(double sol)
{
    printf("%.6lf",sol);
}
void printf(Coord sol)
{
    printf("("),printf(sol.X),printf(","),
           printf(sol.Y),printf(")");
}
void printf(Circle sol)
{
    printf("("),printf(sol.c.X),printf(","),
           printf(sol.c.Y),printf(","),
           printf(sol.r),printf(")");
}
template<typename T>
void printf(vector<T> sol)
{
    sort(sol.begin(),sol.end(),cmpCoord);
    printf("[");
    for(int i=0; i!=sol.size(); ++i)
        printf(i?",":""),printf(sol[i]);
    printf("]");
}
int main()
{
    for(char s[128]; ~scanf("%s",s); printf("\n"))
    {
        if(!strcmp(s,"CircumscribedCircle"))
        {
            Coord p[3]= {getCoord(),getCoord(),getCoord()},
                        p0=(p[1]+p[2])/2.0,
                        p2=(p[1]+p[0])/2.0;
            Line l0(p0,Normal(p[2]-p[1])),
                 l2(p2,Normal(p[0]-p[1]));

            Circle sol(getLineIntersection(l0,l2));
            sol.r=abs(sol.c-p[1]);
            printf(sol);
        }
        else if(!strcmp(s,"InscribedCircle"))
        {
            Coord p[3]= {getCoord(),getCoord(),getCoord()};
            double arg0=(arg(p[1]-p[0])+arg(p[2]-p[0]))/2,
                   arg2=(arg(p[1]-p[2])+arg(p[0]-p[2]))/2;
            Line l0(p[0],polar(1.0,arg0)),
                 l2(p[2],polar(1.0,arg2));

            Circle sol(getLineIntersection(l0,l2));
            sol.r=fabs(DistanceToLine(sol.c,Line(p[0],p[2]-p[0])));
            printf(sol);
        }
        else if(!strcmp(s,"TangentLineThroughPoint"))
        {
            Circle C(getCoord());
            C.r=getd();
            Coord P=getCoord();
            vector<Coord> ans;
            getTangents(P,C,ans);

            vector<double> sol;
            for(int i=0; i!=ans.size(); ++i)
            {
                sol.push_back(arg(ans[i]-P)*180/PI);
                if(sol.back()<0)sol.back()+=180;
            }
            printf(sol);
        }
        else if(!strcmp(s,"CircleThroughAPointAndTangentToALineWithRadius"))
        {
            Circle C(getCoord());
            Coord p[2]= {getCoord(),getCoord()};
            C.r=getd();
            Coord mov=Normal(p[1]-p[0])*C.r;
            Line L0(p[0]+mov,p[1]-p[0]),L1(p[0]-mov,p[1]-p[0]);

            vector<Coord> sol;
            getLineCircleIntersection(L0,C,sol);
            getLineCircleIntersection(L1,C,sol);
            printf(sol);
        }
        else if(!strcmp(s,"CircleTangentToTwoLinesWithRadius"))
        {
            Coord p[4]= {getCoord(),getCoord(),getCoord(),getCoord()};
            double r=getd();
            Coord mov=Normal(p[1]-p[0])*r;
            Line L0(p[0]+mov,p[1]-p[0]),L1(p[0]-mov,p[1]-p[0]);
            mov=Normal(p[3]-p[2])*r;
            Line L2(p[2]+mov,p[3]-p[2]),L3(p[2]-mov,p[3]-p[2]);

            vector<Coord> sol;
            sol.push_back(getLineIntersection(L0,L2));
            sol.push_back(getLineIntersection(L0,L3));
            sol.push_back(getLineIntersection(L1,L2));
            sol.push_back(getLineIntersection(L1,L3));
            printf(sol);
        }
        else if(!strcmp(s,"CircleTangentToTwoDisjointCirclesWithRadius"))
        {
            Circle C[2];
            for(int i=0; i!=2; ++i)
                C[i].c=getCoord(),C[i].r=getd();
            double r=getd();
            C[0].r+=r,C[1].r+=r;

            vector<Coord> sol;
            getCircleIntersection(C[0],C[1],sol);
            printf(sol);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/w_weilan/article/details/78859194
今日推荐