ch_g

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

[HDU 3623 / TJU 3740][坐标旋转](2010天津网络赛C题)

Posted on 2011-03-04 12:36  ch_g  阅读(258)  评论(0编辑  收藏  举报
/*
题目:Covering Points
题目来源:HDU 3623 / TJU 3740 (2010天津网络赛C题)
题目内容或思路:
  坐标旋转
  其实这题感觉上也不是太大自然,不过不知道为什么比赛的时候过队的比较少。
  最让我兴奋的是此题居然是1A的。
  不过遗憾的是先看了Roba的解题报告。
  思路在Roba大牛的blog上有http://roba.rushcj.com/?p=523#comments
做题日期:2011.3.4
*/
#include
<cstdio>
#include
<cstdlib>
#include
<climits>
#include
<iostream>
#include
<algorithm>
#include
<cstring>
#include
<string>
#include
<queue>
#include
<map>
#include
<vector>
#include
<bitset>
#include
<cmath>
#include
<set>
#include
<utility>
using namespace std;

const double eps = 1e-9;
const double inf = 1e100;
const double pi = acos(-1.0);
const int N = 10010;
int n, m;
double ang[N];
double h0, h1, w0, w1, xl, xr, yl, yr;

struct cpoint {
double x, y;
cpoint() {}
cpoint(
double x, double y) : x(x), y(y) {}
}cp[N], ch[N], bp;

int dcmp(double x) {
if (x < -eps) return -1; else return x > eps;
}

double sqr(double x) { return x * x; }

double dissqr(cpoint p1, cpoint p2) {
return sqrt(sqr(p1.x - p2.x) + sqr(p1.y - p2.y));
}

double cross(cpoint p0, cpoint p1, cpoint p2) {
return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y);
}

bool PointEqual(cpoint a, cpoint b) {
return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;
}

int PolarCmp(const cpoint &p1, const cpoint &p2) {
int u = dcmp(cross(bp, p1, p2));
return u > 0 || (u == 0 && dcmp(dissqr(bp, p1) - dissqr(bp, p2)) < 0 );
}

void graham(cpoint pin[], int n, cpoint ch[], int &m) {
int i, j, k, u, v;
memcpy(ch, pin, n
* sizeof(cpoint));
for (i = k = 0; i < n; ++i) {
u
= dcmp(ch[i].x - ch[k].x);
v
= dcmp(ch[i].y - ch[k].y);
if (v < 0 || (v == 0 && u < 0)) k = i;
}
bp
= ch[k];
sort(ch, ch
+ n, PolarCmp);
n
= unique(ch, ch + n, PointEqual) - ch;
if (n <= 1) {m = n; return;}
if (dcmp(cross(ch[0], ch[1], ch[n - 1])) == 0) {
m
= 2; ch[1] = ch[n - 1]; return;
}
ch[n
++] = ch[0];
for (i = 1, j = 2; j < n; ++j) {
while (i > 0 && dcmp(cross(ch[i - 1], ch[i], ch[j])) <= 0)i--;
ch[
++i] = ch[j];
}
m
= i;
}

cpoint rotate(cpoint v,
double angle) {
cpoint res;
double c, s;
c
= cos(angle);
s
= sin(angle);
res.x
= v.x * c - v.y * s;
res.y
= v.x * s + v.y * c;
return res;
}

void rotate(cpoint ch[], cpoint cp[], int m, double angle) {
xl
= yl = inf;
xr
= yr = -inf;
for (int i = 0; i < m; ++i) {
cp[i]
= rotate(ch[i], angle);
xl
= min(xl, cp[i].x);
xr
= max(xr, cp[i].x);
yl
= min(yl, cp[i].y);
yr
= max(yr, cp[i].y);
}
w1
= xr - xl;
h1
= yr - yl;
}

int check(double angle) {
rotate(ch, cp, m, angle);
if (dcmp(w1 - h1) == 0) return 0;
if (dcmp(w0 - h0) * dcmp(w1 - h1) <= 0) return -1;
return 1;
}

void solve() {
double x, y;
int i;
for (i = 0; i < n; ++i) {
scanf(
"%lf%lf", &cp[i].x, &cp[i].y);
}
graham(cp, n, ch, m);
if (m < 3) {
printf(
"%.8lf %.8lf\n", ch[0].x, ch[0].y);
x
= ( ch[0].x + ch[1].x - ch[0].y + ch[1].y) / 2;
y
= ( ch[0].x - ch[1].x + ch[0].y + ch[1].y) / 2;
printf(
"%.8lf %.8lf\n", x, y);
printf(
"%.8lf %.8lf\n", ch[1].x, ch[1].y);
x
= ( ch[0].x + ch[1].x + ch[0].y - ch[1].y) / 2;
y
= (-ch[0].x + ch[1].x + ch[0].y + ch[1].y) / 2;
printf(
"%.8lf %.8lf\n", x, y);
return;
}
n
= 0;
ch[m]
= ch[0];
for (i = 0; i < m; ++i) {
ang[n
++] = -atan2(ch[i + 1].y - ch[i].y, ch[i + 1].x - ch[i].x);
}
sort(ang, ang
+ n);
n
= unique(ang, ang + n) - ang;
for (i = 0; i < n; ++i) {
rotate(ch, cp, m, ang[i]);
if (i && dcmp(w0 - h0) * dcmp(w1 - h1) <= 0) break;
w0
= w1;
h0
= h1;
}
double low, high, mid;
if (i == n) {
low
= ang[n - 1];
high
= ang[0] + pi * 2;
}
else {
low
= ang[i - 1];
high
= ang[i];
}
while (1) {
mid
= (low + high) / 2;
int t = check(mid);
if (t == 0) break;
if (t == 1) low = mid;
else high = mid;
}
bp
= rotate(cpoint(xl, yl), -mid);
printf(
"%.8lf %.8lf\n", bp.x, bp.y);
bp
= rotate(cpoint(xr, yl), -mid);
printf(
"%.8lf %.8lf\n", bp.x, bp.y);
bp
= rotate(cpoint(xr, yr), -mid);
printf(
"%.8lf %.8lf\n", bp.x, bp.y);
bp
= rotate(cpoint(xl, yr), -mid);
printf(
"%.8lf %.8lf\n", bp.x, bp.y);
}

int main() {
#ifndef ONLINE_JUDGE
freopen(
"D:\\in.txt", "r", stdin);
#endif
int cas = 0;
while (scanf("%d", &n), n) {
if (cas) puts("");
printf(
"Case %d:\n", ++cas);
solve();
}
return 0;
}