http://poj.org/problem?id=3384

题意:给一个凸包,求往里面放两个圆(可重叠)的最大面积时的两个圆心坐标。

思路:先把凸包边往内推R,做半平面交,然后做旋转卡壳,此时得到最大距离的点对,就是圆心坐标。

PS:最大长度的初始值要设置为负数,因为距离有可能退化到0,就像这组数据

4 1

0 0

2 0

2 2

0 2

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
const double Pi=acos(-);
double R;
int n,tot;
struct Point{
double x,y;
Point(){}
Point(double x0,double y0):x(x0),y(y0){}
}p[];
struct Line{
Point s,e;
double slop;
Line(){}
Line(Point s0,Point e0):s(s0),e(e0){}
}L[],l[],c[];
int read(){
int t=,f=;char ch=getchar();
while (ch<''||ch>''){if (ch=='-')f=-;ch=getchar();}
while (''<=ch&&ch<=''){t=t*+ch-'';ch=getchar();}
return t*f;
}
Point operator /(Point p1,double x){
return Point(p1.x/x,p1.y/x);
}
Point operator *(Point p,double x){
return Point(p.x*x,p.y*x);
}
double operator *(Point p1,Point p2){
return p1.x*p2.y-p1.y*p2.x;
}
Point operator -(Point p1,Point p2){
return Point(p1.x-p2.x,p1.y-p2.y);
}
Point operator +(Point p1,Point p2){
return Point(p1.x+p2.x,p1.y+p2.y);
}
bool cmp(Line p1,Line p2){
if (p1.slop!=p2.slop) return p1.slop<p2.slop;
else return (p1.e-p1.s)*(p2.e-p1.s)<=;
}
Point inter(Line p1,Line p2){
double k1=(p2.e-p1.s)*(p1.e-p1.s);
double k2=(p1.e-p1.s)*(p2.s-p1.s);
double t=(k2)/(k1+k2);
double x=p2.s.x+(p2.e.x-p2.s.x)*t;
double y=p2.s.y+(p2.e.y-p2.s.y)*t;
return Point(x,y);
}
bool jud(Line p1,Line p2,Line p3){
Point p=inter(p1,p2);
return (p-p3.s)*(p3.e-p3.s)>;
}
void phi(){
std::sort(l+,l++tot,cmp);
int cnt=;
for (int i=;i<=tot;i++)
if (l[i].slop!=l[i-].slop)
l[++cnt]=l[i];
int L=,R=;c[L]=l[];c[R]=l[];
for (int i=;i<=cnt;i++){
while (L<R&&jud(c[R],c[R-],l[i])) R--;
while (L<R&&jud(c[L],c[L+],l[i])) L++;
c[++R]=l[i];
}
while (L<R&&jud(c[R],c[R-],c[L])) R--;
while (L<R&&jud(c[L],c[L+],c[R])) L++;
tot=;
c[R+]=c[L];
for (int i=L;i<=R;i++)
p[++tot]=inter(c[i],c[i+]);
}
double sqr(double x){
return x*x;
}
double dis(Point p){
return sqrt(sqr(p.x)+sqr(p.y));
}
Point turn(Point p,double ang){
double Cos=cos(ang),Sin=sin(ang);
double x=Cos*p.x-Sin*p.y;
double y=Cos*p.y+Sin*p.x;
return Point(x,y);
}
Point e(Point p){
double len=dis(p);p=p/len;return p;
}
double dis(Point p1,Point p2){
return dis(p1-p2);
}
void rc(){
p[tot+]=p[];
int k=;
double mx=-;
Point ans1,ans2;
for (int i=;i<=tot;i++){
while (fabs((p[i%tot+]-p[i])*(p[k]-p[i]))<fabs((p[i%tot+]-p[i])*(p[k%tot+]-p[i]))) k=(k)%tot+;
if (mx<dis(p[i],p[k])){
mx=dis(p[i],p[k]);
ans1=p[i];
ans2=p[k];
}
}
printf("%.4f %.4f %.4f %.4f",ans1.x,ans1.y,ans2.x,ans2.y);
}
int main(){
n=read(),R=read();
for (int i=;i<=n;i++) p[i].x=read(),p[i].y=read();
for (int i=;i<=n/;i++) std::swap(p[i],p[n-i+]);
p[n+]=p[];
for (int i=;i<=n;i++)
l[++tot]=Line(p[i],p[i+]),l[tot].slop=atan2(l[tot].e.y-l[tot].s.y,l[tot].e.x-l[tot].s.x);
for (int i=;i<=n;i++){
Point p=e(turn((l[i].e-l[i].s),Pi/2.0))*R;
l[i].s=l[i].s+p;
l[i].e=l[i].e+p;
}
phi();
rc();
}

POJ 3384 Feng Shui的更多相关文章

  1. poj 3384 Feng Shui (Half Plane Intersection)

    3384 -- Feng Shui 构造半平面交,然后求凸包上最远点对. 这题的题意是给出一个凸多边形区域,要求在其中放置两个半径为r的圆(不能超出凸多边形区域),要求求出两个圆心,使得多边形中没有被 ...

  2. POJ 3384 Feng Shui 半平面交

    题目大意:一个人很信"Feng Shui",他要在房间里放两个圆形的地毯. 这两个地毯之间可以重叠,可是不能折叠,也不能伸到房间的外面.求这两个地毯可以覆盖的最大范围.并输出这两个 ...

  3. POJ 3384 Feng Shui (半平面交)

    Feng Shui Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 3743   Accepted: 1150   Speci ...

  4. POJ 3384 Feng Shui(计算几何の半平面交+最远点对)

    Description Feng shui is the ancient Chinese practice of placement and arrangement of space to achie ...

  5. POJ 3384 Feng Shui --直线切平面

    题意:房间是一个凸多边形,要在里面铺设两条半径为r的圆形地毯,可以重叠,现在要求分别铺设到哪,使地毯所占的地面面积最大. 解法:要使圆形地毯所占面积最大,圆形地毯一定是与边相切的,这样才能使尽量不重叠 ...

  6. POJ 3384 Feng Shui(半平面交向内推进求最远点对)

    题目链接 题意 : 两个圆能够覆盖的最大多边形面积的时候两个圆圆心的坐标是多少,两个圆必须在多边形内. 思路 : 向内推进r,然后求多边形最远的两个点就是能覆盖的最大面积. #include < ...

  7. POJ 3384 Feng Shui 凸包直径 + 半平面交

    G++一直没有过了 换成 C++果断A掉了...It's time to bet RP. 题意:给一个多边形,然后放进去两个圆,让两个圆的覆盖面积尽量最大,输出两个圆心的坐标. 思路:将多边形的边向里 ...

  8. poj 3384 半平面交

    Feng Shui Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 5183   Accepted: 1548   Speci ...

  9. POJ3384:Feng Shui——题解

    http://poj.org/problem?id=3384 题目大意:给一个顺时针序的多边形,求在里面放半径为r的两个圆使得两圆覆盖的面积最大,求出这样的圆的坐标. ———————————————— ...

随机推荐

  1. 【转】java byte转long、double、float、int、short,或者long、double、float、int、short转byte

    原文网址:http://www.xuebuyuan.com/988752.html java byte与其他数据类型的转换主要用于二进制数据的编码和解码,主要用于网络传输,读写二进制文件,java和c ...

  2. POJ_3083——贴左右墙DFS,最短路径BFS

    Description The cornfield maze is a popular Halloween treat. Visitors are shown the entrance and mus ...

  3. ios9邮箱添加163邮箱

    电脑登陆163邮箱➡️设置➡️开启pop3/smtp/imap功能➡️保存.开启后系统会给你个"客户端授权密码",同时会发短信到你手机里. 打开手机,设置➡️邮件,通讯录,日历➡️ ...

  4. HDU4432 Sum of Divisors

    涉及知识点: 1. 进制转换. 2. 找因子时注意可以降低复杂度. Sum of divisors Time Limit: 2000/1000 MS (Java/Others)    Memory L ...

  5. Java如何让异常处理机制更完备规范

    1)catch的Exception一定要详细的点名是某种异常而非一概而论的用Exception ex来接收所有的异常,往往不理解这点的人也不能很好的理解catch的意义到底在哪里,是对捕获的异常进行一 ...

  6. Java Hibernate 之连接池详解

    Hibernate支持第三方的连接池,官方推荐的连接池是C3P0,Proxool,以及DBCP.在配置连接池时需要注意的有三点: 一.Apche的DBCP在Hibernate2中受支持,但在Hiber ...

  7. POJ 2886 Who Gets the Most Candies? 线段树。。还有方向感

    这道题不仅仅是在考察线段树,还他妹的在考察一个人的方向感.... 和线段树有关的那几个函数写了一遍就对了,连改都没改,一直在转圈的问题的出错.... 题意:从第K个同学开始,若K的数字为正 则往右转, ...

  8. [深入React] 9.小技巧

    如果组件没有state那就可以精简成一个render function var Item = function(props){ return _('div',null,'名称:'+props.name ...

  9. leetcode:Palindrome Number (判断数字是否回文串) 【面试算法题】

    题目: Determine whether an integer is a palindrome. Do this without extra space. Some hints: Could neg ...

  10. hdu 2013

    水题 AC代码: #include <iostream> using namespace std; int main() { int i,m,n; while(cin>>n) ...