zoukankan      html  css  js  c++  java
  • Ural 1046 Geometrical Dreams(解方程+计算几何)

    题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1046

    参考博客:http://hi.baidu.com/cloudygoose/item/21fee021a5db348d9d63d17b

    参考资料(向量的旋转):http://www.cnblogs.com/woodfish1988/archive/2007/09/10/888439.html

    题目大意:就是已知n个点,n个角。点Mi可以与多边形Ai和Ai+1构成等腰三角形,顶角为ang[i].  现在要你求出这个多边形的n的顶点。

    算法思路:刚开始想几何性质,怎么也想不出来一个好的思路。没办法,网搜才知道要用解方程的方法。蛋疼的是没写过,别人的代码有是懂非懂的。慢慢琢磨才发现其实现方程求解的思路。先看看那个参考博客的思路吧。

    我只是大致翻译一下他的思想: 我们知道: Ai+1 = Rotate(Ai-Mi,ang[i]) + Mi;  (画画图就知道)                整理下就是:Ai+1 = P1' * Ai + P2';

    而由A1递推来 :   Ai = P1 * A1 + P2;        我们编程时要不断更新这个P1和P2;

    具体看代码:

    代码:

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    using namespace std;
    
    const double eps = 1e-8;
    const double PI = acos(-1.0);
    const double INF = 1000000000000000.000;
    
    struct Point{
        double x,y;
        Point(double x=0, double y=0) : x(x),y(y){ }    //构造函数
    };
    typedef Point Vector;
    
    struct Circle{
         Point c;
         double r;
         Circle() {}
         Circle(Point c,double r): c(c),r(r) {}
    };
    Vector operator + (Vector A , Vector B){return Vector(A.x+B.x,A.y+B.y);}
    Vector operator - (Vector A , Vector B){return Vector(A.x-B.x,A.y-B.y);}
    Vector operator * (double p,Vector A){return Vector(A.x*p,A.y*p);}
    Vector operator / (Vector A , double p){return Vector(A.x/p,A.y/p);}
    
    bool operator < (const Point& a,const Point& b){
        return a.x < b.x ||( a.x == b.x && a.y < b.y);
    }
    
    int dcmp(double x){
        if(fabs(x) < eps) return 0;
        else              return x < 0 ? -1 : 1;
    }
    bool operator == (const Point& a, const Point& b){
        return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;
    }
    
    ///向量(x,y)的极角用atan2(y,x);
    inline double Dot(Vector A, Vector B){ return A.x*B.x + A.y*B.y; }
    inline double Length(Vector A)    { return sqrt(Dot(A,A)); }
    inline double Angle(Vector A, Vector B)  { return acos(Dot(A,B) / Length(A) / Length(B)); }
    double Cross(Vector A, Vector B)  { return A.x*B.y - A.y * B.x; }
    
    Vector vecunit(Vector v){ return v / Length(v);} //单位向量
    double torad(double deg) { return deg/180 * PI; }
    Vector Rotate(Vector A, double rad) { return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad)); }
    
    
    /*************************************分 割 线*****************************************/
    
    int main()
    {
        //freopen("E:\acm\input.txt","r",stdin);
    
        const int maxn = 60;
        Point M[maxn],P1,P2;
    
        double ang[maxn];
        int n;
    
        cin>>n;
        for(int i=1; i<=n; i++)
        {
            scanf("%lf %lf",&M[i].x,&M[i].y);
        }
        for(int i=1; i<=n; i++)
        {
            scanf("%lf",&ang[i]);
            ang[i] = torad(ang[i]);
        }
    
        P1 = Point(1,0);
        P2 = Point(0,0);
    
        for(int i=1; i<=n; i++)
        {
            P1 = Rotate(P1,ang[i]);
            P2 = Rotate(P2,ang[i]);
            P2 = P2 + M[i] - Rotate(M[i],ang[i]);
        }
    
        P1.x -= 1;
        P2.x = -P2.x;
        P2.y = -P2.y;
    
        Point ans;  //求ans时,把P1,P2看成复平面中的点,即P1表示为P1.x+P2.y*i; 然后ans = P2/P1,用虚数就可求出。
        ans.x = (P1.x*P2.x+P1.y*P2.y)/(P1.x*P1.x+P1.y*P1.y);
        ans.y = (-P1.y*P2.x+P1.x*P2.y)/(P1.x*P1.x+P1.y*P1.y);
    
        for(int i=1; i<=n; i++)
        {
            printf("%.2lf %.2lf
    ",ans.x,ans.y);
            ans = M[i] + Rotate(ans-M[i],ang[i]);
        }
    }
    View Code
  • 相关阅读:
    vs快速添加引用解析的快捷键
    Linux内核调试技术——kprobe使用与实现
    Linux内核调试技术——kretprobe使用与实现
    Linux内核调试技术——jprobe使用与实现
    【HTTP协议】---HTTP协议详解
    雪崩效应
    Shell中IFS用法
    shell中for循环,读取一整行
    BCD码
    pam模块日志怎么输出
  • 原文地址:https://www.cnblogs.com/acmdeweilai/p/3337788.html
Copyright © 2011-2022 走看看