HDU 4998 Rotate

题目链接

思路:构造一个多边形,顶点集由边界顶点和旋转中心点组成。将此多边形绕每个中心点旋转相应角度,得到新的多边形,任取原多边形和新多边形的两条对应边,分别作中垂线,直到两中垂线平行为止。两中垂线的交点即为旋转中心A,旋转角p为每个旋转角的和,注意将其对2π取模,p = fmod(p, 2*acos(-1.0));

//Rotate.cpp
#include <ios>
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <cctype>
#include <cerrno>
#include <cfloat>
#include <cstdio>
#include <cwchar>
#include <iosfwd>
#include <limits>
#include <locale>
#include <memory>
#include <string>
#include <vector>
#include <cassert>
#include <ciso646>
#include <climits>
#include <clocale>
#include <complex>
#include <csetjmp>
#include <csignal>
#include <cstdarg>
#include <cstddef>
#include <cstdlib>
#include <cstring>
#include <cwctype>
#include <fstream>
#include <iomanip>
#include <istream>
#include <numeric>
#include <ostream>
#include <sstream>
#include <utility>
#include <iostream>
#include <iterator>
#include <valarray>
#include <algorithm>
#include <exception>
#include <stdexcept>
#include <streambuf>
#include <functional>
#define LL long long
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#define PI 3.1415926535897932626
#define mid(n) ((center[n]+pol.a[n])*0.5)
#define CLEAR(name, init) memset(name, init, sizeof(name))
const double eps = 1e-8;
const int MAXN = (int)1e9 + 5;
using namespace std;
struct Point {
    double x, y;
    Point(double x = 0.0, double y = 0.0): x(x), y(y) { }
};
struct Polygon {
    int n;
    Point a[20];
    Polygon() {}
};
typedef Point Vector;
Vector operator + (Vector A, Vector B) { return Vector(A.x+B.x, A.y+B.y); }
Vector operator - (Point A, Point B) { return Vector(A.x-B.x, A.y-B.y); }
Vector operator * (Vector A, double p) { return Vector(A.x*p, A.y*p); }
Vector operator / (Vector A, double p) { return Vector(A.x/p, A.y/p); }
double Dot(Vector A, Vector B) { return A.x*B.x + A.y*B.y; }
double Length(Vector A) { return sqrt(Dot(A, A)); }
double Cross(Vector A, Vector B) { return A.x*B.y - A.y*B.x; }
Point rotate(Vector A, double alpha) {
    double cos_rad = cos(alpha), sin_rad = sin(alpha);
    return Vector(A.x*cos_rad-A.y*sin_rad, A.x*sin_rad+A.y*cos_rad);
}
Point GetLineIntersection(Point P, Vector v, Point Q, Vector w) {
    Vector u = P - Q;
    double t = Cross(w, u) / Cross(v, w);
    return P + v*t;
}
struct line {
    Point a,b;
    line(){}
    line(Point x,Point y):a(x),b(y){}
};
int dblcmp(double x) {
    if (fabs(x) < eps) return 0;
    return x > 0 ? 1 : -1;
}
bool parallel(line a,line b) {
    return !dblcmp(Cross(a.a-a.b,b.a-b.b));
}
int main(int argc, char const *argv[]) {
#ifndef ONLINE_JUDGE
    freopen("D:\\Documents\\Programs\\Acm\\input.txt", "r", stdin);
#endif
    int T; cin >> T;
    while(T--) {
        int n; cin >> n;
        Point left_up = Point(0.0, 100.0);
        Point right_up = Point(100.0, 100.0);
        Point left_down = Point(0.0, 0.0);
        Point right_down = Point(100.0, 0.0);
        Polygon pol;
        pol.n = n + 4;
        pol.a[0] = left_up; pol.a[1] = right_up;
        pol.a[2] = left_down; pol.a[3] = right_down;
        Point center[20];
        double rad[20], p = 0.0;
        for(int i = 0; i < n; i++) {
            scanf("%lf%lf%lf", ¢er[i+4].x, ¢er[i+4].y, &rad[i+4]);
            pol.a[i+4] = center[i+4];
            p += rad[i+4];
        }
        for(int i = 0; i < 4; i++) center[i] = pol.a[i];
        while(p >= 2*acos(-1.0)) p -= 2*acos(-1.0);
        for(int i = 4; i < pol.n; i++) {
            for(int j = 0; j < pol.n; j++) {
                pol.a[j] = rotate(pol.a[j]-center[i], rad[i]) + center[i];
            }
        }
        Point res;
        for (int i = 0; i < pol.n; i++) {
            for (int j = i+1; j < pol.n; j++) {
                Point p1 = (center[i]+pol.a[i]) * 0.5;
                Point q1 = (center[j]+pol.a[j]) * 0.5;
                Point p2 = rotate(center[i]-p1, PI/2.0)+p1;
                Point q2 = rotate(center[j]-q1, PI/2.0)+q1;
                line P = line(p1, p2), Q = line(q1, q2);
                if (parallel(P,Q)) continue;
                double s1=Cross(p1-q1, q2-q1);
                double s2=Cross(p2-q1, q2-q1);
                res = (p2*s1-p1*s2)/(s1-s2);
            }
        }
        printf("%.10lf %.10lf %.10lf\n", res.x, res.y, p);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值