博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

[poj][2600][Geometrical dreams]

Posted on 2012-07-12 19:40  紫华弦筝  阅读(166)  评论(0编辑  收藏  举报

题目:http://poj.org/problem?id=2600

复数旋转+模拟退火。一开始还被复数吓到了(没学过啊),查了一下,跟坐标旋转很像啊。。。

View Code
#include <cstdio>
#include <cmath>
#include <algorithm>

#define dis(a,b) sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y))
using namespace std;

const double pi = acos(-1.0);
const double eps = 1e-8;

struct node{
    double x, y;
    node(){}
    node(double x, double y):x(x),y(y){}
    void get(){ scanf("%lf%lf", &x, &y); }
}p[55], q[55];

int n;
bool ok;
double a[55];

void rotating(node tmp, node o, double angle, node &g){
    double dx=tmp.x-o.x, dy=tmp.y-o.y;
    g.x = dx * cos(angle) - dy * sin(angle) + o.x;
    g.y = dx * sin(angle) + dy * cos(angle) + o.y;
}

int dx[]={1,-1, 0, 0, 1,-1, 0, 0};
int dy[]={0, 0, 1,-1, 0, 0, 1,-1};

int main(){
    //freopen("D:/a.txt", "r", stdin);
    while (~scanf("%d", &n)){
        ok = false;
        for (int i=0; i<n; i++) p[i].get();
        for (int i=0; i<n; i++) scanf("%lf", &a[i]), a[i]*=pi/180;
        q[0] = node(0,0);
        for (double t=2000; t>eps && !ok; t*=0.88){
            for (int i=0; i<8 && !ok; i++){
                node tmp(q[0].x+dx[i]*t,q[0].y+dy[i]*t);
                for (int j=1; j<=n && !ok; j++){
                    rotating(q[j-1],p[j-1],a[j-1],q[j]);
                }
                if (fabs(dis(q[n],tmp)-dis(q[n],q[0]))<eps)ok=true;
                if (dis(q[n],q[0])>dis(q[n],tmp))q[0]=tmp;
            }
        }
        for (int i=0; i<n; i++)
            printf("%.0f %.0f\n", q[i].x, q[i].y);
    }
    return 0;
}