POJ 3384 || Feng Shui (半平面交内推R

来源:互联网 发布:淘宝苏宁买手机可靠吗 编辑:程序博客网 时间:2024/05/16 04:35

题目大意:给你一个凸包,里面放两个半径相同的圆,问你如果让这两个圆覆盖凸包的面积最大。

两个圆可以覆盖重合,但不是不会跑到墙角折起来。输出放置圆的两个圆的圆心坐标。如果有多种可能,输出任意一种。

思路:

半平面交内推R,求目前这个核最远的两点,因为半径固定,两个圆的圆心离的越开,你们覆盖的凸包的面积也就越大。

        1.半平面交内推R

        2.暴力扫描一边核(就是一个新的凸包)的点,算出距离最远的两个点,就输出。

代码:78ms c++

#include <iostream>#include <cstdio>#include <cmath>#include <algorithm>using namespace std;const double eps = 1e-8;struct pnode{    double x,y;    pnode(double xx=0.0,double yy=0.0):x(xx),y(yy){}    //绕原点旋转角度a(弧度)    void tansxy(double a){        double tx = x,ty= y;        x = tx*cos(a) - ty*sin(a);        y = tx*sin(a) + ty*cos(a);    }}p[105],tp[105],q[105];double dist(pnode p1,pnode p2){    return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));}//通过两点,确定直线方程void get_line( pnode p1,pnode p2,double &a,double &b,double &c){    a = p2.y - p1.y;    b = p1.x - p2.x;    c = p2.x*p1.y - p1.x*p2.y;}//求交点pnode line_inter_point(pnode p1,pnode p2,double a,double b,double c){    double u = fabs(a*p1.x+b*p1.y+c);    double v = fabs(a*p2.x+b*p2.y+c);    pnode t;    t.x = ( p1.x*v + p2.x*u )/(u+v);    t.y = ( p1.y*v + p2.y*u )/(u+v);    return t;}//顺时针,加入一条边,切割void cut( pnode p[],int &cnt,double a,double b,double c){    int tmp = 0;    for( int i = 1;i<= cnt;++i){        //当前点在右侧 逆时针为在左侧 改为  if( <eps )        if( a*p[i].x + b*p[i].y + c > -eps)            tp[++tmp] = p[i];        else{            if( a*p[i-1].x + b*p[i-1].y +c > eps )                tp[++tmp] = line_inter_point(p[i-1],p[i],a,b,c);            if( a*p[i+1].x + b*p[i+1].y +c > eps )                tp[++tmp] = line_inter_point(p[i],p[i+1],a,b,c);        }    }    for( int i = 1; i <= tmp ;++i)        p[i] = tp[i];    p[0] = p[tmp];    p[tmp+1] = p[1];    cnt = tmp;}void solve(pnode q[],int n,double r){    q[0]=q[n];    q[n+1]=q[1];    for(int i=0;i<=n+1;i++) p[i]=q[i];    int cnt=n;    for(int i=1;i<=n;i++){        double a,b,c;        pnode p1( q[i+1].y-q[i].y ,q[i].x-q[i+1].x);        double k=r/sqrt(p1.x*p1.x+p1.y*p1.y);        p1.x=k*p1.x;p1.y=p1.y*k;        pnode p2 (p1.x+q[i].x,p1.y+q[i].y );        pnode p3 (p1.x+q[i+1].x,p1.y+q[i+1].y );        get_line(p2,p3,a,b,c);        cut(p,cnt,a,b,c);    }    double maxdist=0,d;    pnode p1,p2;    for(int i=1;i<=cnt;i++)        for(int j=1;j<=cnt;j++){            d=dist(p[i],p[j]);            if(d+eps>maxdist){                maxdist=d;                p1=p[i];                p2=p[j];            }        }    printf("%.4lf %.4lf %.4lf %.4lf\n",p1.x,p1.y,p2.x,p2.y);}int main(){    int n,r;    while( ~scanf("%d %d",&n,&r)){        for( int i = 1;i <= n;++i)            scanf("%lf %lf",&q[i].x,&q[i].y);        solve(q,n,r);    }    return 0;}


0 0
原创粉丝点击