当前位置: 首页 > news >正文

POJ 3384 Feng Shui

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(-1);
double R;
int n,tot;
struct Point{
    double x,y;
    Point(){}
    Point(double x0,double y0):x(x0),y(y0){}
}p[200005];
struct Line{
    Point s,e;
    double slop;
    Line(){}
    Line(Point s0,Point e0):s(s0),e(e0){}
}L[200005],l[200005],c[200005];
int read(){
    int t=0,f=1;char ch=getchar();
    while (ch<'0'||ch>'9'){if (ch=='-')f=-1;ch=getchar();}
    while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';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)<=0;
}
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)>0;
}
void phi(){
    std::sort(l+1,l+1+tot,cmp);
    int cnt=1;
    for (int i=2;i<=tot;i++)
     if (l[i].slop!=l[i-1].slop)
      l[++cnt]=l[i];
    int L=1,R=2;c[L]=l[1];c[R]=l[2];
    for (int i=3;i<=cnt;i++){
        while (L<R&&jud(c[R],c[R-1],l[i])) R--;
        while (L<R&&jud(c[L],c[L+1],l[i])) L++;
        c[++R]=l[i];
    }  
    while (L<R&&jud(c[R],c[R-1],c[L])) R--;
    while (L<R&&jud(c[L],c[L+1],c[R])) L++;
    tot=0;
    c[R+1]=c[L];
    for (int i=L;i<=R;i++)
     p[++tot]=inter(c[i],c[i+1]);
}
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+1]=p[1];
    int k=2;
    double mx=-1;
    Point ans1,ans2;
    for (int i=1;i<=tot;i++){
        while (fabs((p[i%tot+1]-p[i])*(p[k]-p[i]))<fabs((p[i%tot+1]-p[i])*(p[k%tot+1]-p[i]))) k=(k)%tot+1;
        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=1;i<=n;i++) p[i].x=read(),p[i].y=read();
    for (int i=1;i<=n/2;i++) std::swap(p[i],p[n-i+1]);
    p[n+1]=p[1];
    for (int i=1;i<=n;i++)
     l[++tot]=Line(p[i],p[i+1]),l[tot].slop=atan2(l[tot].e.y-l[tot].s.y,l[tot].e.x-l[tot].s.x); 
    for (int i=1;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();
}

 

转载于:https://www.cnblogs.com/qzqzgfy/p/5657500.html

相关文章:

  • Android环境下hanlp汉字转拼音功能的使用介绍
  • 轻松搭建docker应用的mesos集群
  • Android Studio发布Release版本之坑--Unknown host 'd29vzk4ow07wi7.cloudfront.net'
  • Spring—Quartz定时调度CronTrigger时间配置格式说明与实例
  • 一步步教你用 CSS 为 SVG 添加过滤器
  • js学习笔记之日期倒计时(天,时,分,秒)
  • iOS app和Extension数据共享DB时候遇到的坑 NSFileManager共享数据的坑
  • ASP.NET MVC学习之路由篇(2)
  • 用Go语言写Android应用 (2) - 从Android的Java调用Go代码
  • RootMe--HTTP - Open redirect
  • SerializeDeserialize
  • Unity3dShader边缘发光效果
  • 利用python jieba库统计政府工作报告词频
  • Azure linux centos 默认登陆账号是什么?
  • TeeChart Pro VCL/FMX教程(一):入门——构建图表
  • (ckeditor+ckfinder用法)Jquery,js获取ckeditor值
  • 【407天】跃迁之路——程序员高效学习方法论探索系列(实验阶段164-2018.03.19)...
  • Android 初级面试者拾遗(前台界面篇)之 Activity 和 Fragment
  • Asm.js的简单介绍
  • Dubbo 整合 Pinpoint 做分布式服务请求跟踪
  • js对象的深浅拷贝
  • js继承的实现方法
  • nfs客户端进程变D,延伸linux的lock
  • React Transition Group -- Transition 组件
  • Redis的resp协议
  • win10下安装mysql5.7
  • 阿里云购买磁盘后挂载
  • 彻底搞懂浏览器Event-loop
  • 前端存储 - localStorage
  • 使用API自动生成工具优化前端工作流
  • 想写好前端,先练好内功
  • 学习使用ExpressJS 4.0中的新Router
  • 用mpvue开发微信小程序
  • 在Unity中实现一个简单的消息管理器
  • 阿里云ACE认证之理解CDN技术
  • 我们雇佣了一只大猴子...
  • ​直流电和交流电有什么区别为什么这个时候又要变成直流电呢?交流转换到直流(整流器)直流变交流(逆变器)​
  • # Pytorch 中可以直接调用的Loss Functions总结:
  • ###51单片机学习(2)-----如何通过C语言运用延时函数设计LED流水灯
  • #if #elif #endif
  • #pragma预处理命令
  • #QT(串口助手-界面)
  • #我与Java虚拟机的故事#连载10: 如何在阿里、腾讯、百度、及字节跳动等公司面试中脱颖而出...
  • (10)ATF MMU转换表
  • (day6) 319. 灯泡开关
  • (Mirage系列之二)VMware Horizon Mirage的经典用户用例及真实案例分析
  • (pojstep1.1.2)2654(直叙式模拟)
  • (TOJ2804)Even? Odd?
  • (附源码)ssm经济信息门户网站 毕业设计 141634
  • (介绍与使用)物联网NodeMCUESP8266(ESP-12F)连接新版onenet mqtt协议实现上传数据(温湿度)和下发指令(控制LED灯)
  • (使用vite搭建vue3项目(vite + vue3 + vue router + pinia + element plus))
  • (一)pytest自动化测试框架之生成测试报告(mac系统)
  • (转)原始图像数据和PDF中的图像数据
  • (转载)VS2010/MFC编程入门之三十四(菜单:VS2010菜单资源详解)
  • .net通用权限框架B/S (三)--MODEL层(2)