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\n",ans.x,ans.y);
        ans = M[i] + Rotate(ans-M[i],ang[i]);
    }
}
View Code

 

 

posted @ 2013-09-24 22:42  等待最好的两个人  阅读(591)  评论(0编辑  收藏  举报