POJ3384:Feng Shui——题解

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ3384:Feng Shui——题解相关的知识,希望对你有一定的参考价值。

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

题目大意:给一个顺时针序的多边形,求在里面放半径为r的两个圆使得两圆覆盖的面积最大,求出这样的圆的坐标。

————————————————

解题思路:将多边形内缩进r,然后求内核。

枚举点对然后根据点对距离判断是否覆盖面积最大即可。

注意:可能两圆重合。

#include<cstdio>
#include<queue>
#include<cctype>
#include<cstring>
#include<stack>
#include<cmath>
#include<algorithm>
using namespace std;
typedef double dl;
const dl eps=1e-10;
const int N=301;
struct Point{
    dl x;
    dl y;
}p[N],point[N],q[N],z;
//point,初始点 
//q,暂时存可行点
//p,记录可行点 
int n,curcnt,cnt;
dl r;
//curcnt,暂时存可行点个数 
//cnt,记录可行点个数
inline Point getmag(Point a,Point b){
    Point s;
    s.x=b.x-a.x;s.y=b.y-a.y;
    return s;
}
inline dl multiX(Point a,Point b){
    return a.x*b.y-b.x*a.y;
}
inline void getline(Point x,Point y,dl &a,dl &b,dl &c){
    a=y.y-x.y;
    b=x.x-y.x;
    c=y.x*x.y-x.x*y.y;
    return;
}
inline Point intersect(Point x,Point y,dl a,dl b,dl c){
    Point s;
    dl u=fabs(a*x.x+b*x.y+c);  
    dl v=fabs(a*y.x+b*y.y+c);
    s.x=(x.x*v+y.x*u)/(u+v);
    s.y=(x.y*v+y.y*u)/(u+v);
    return s;  
} 
inline void cut(dl a,dl b,dl c){
    curcnt=0;
    for(int i=1;i<=cnt;i++){
        if(a*p[i].x+b*p[i].y+c>-eps)q[++curcnt]=p[i];
        else{
            if(a*p[i-1].x+b*p[i-1].y+c>eps){
                q[++curcnt]=intersect(p[i],p[i-1],a,b,c);
        }
            if(a*p[i+1].x+b*p[i+1].y+c>eps){
                q[++curcnt]=intersect(p[i],p[i+1],a,b,c);
        }
        }
    }
    for(int i=1;i<=curcnt;i++)p[i]=q[i];
    p[curcnt+1]=p[1];p[0]=p[curcnt];
    cnt=curcnt;
    return;
}
inline void init(){
    for(int i=1;i<=n;i++)p[i]=point[i];
    z.x=z.y=0;
    p[n+1]=p[1];
    p[0]=p[n];
    point[n+1]=point[1];
    cnt=n;
    return;
}
inline void regular(){//调换方向 
    for(int i=1;i<(n+1)/2;i++)swap(point[i],point[n-i]);
    return;
}
inline dl dis(Point a,Point b){
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
inline void solve(){
    init();
    for(int i=1;i<=n;i++){
    Point ta,tb,tt;
    tt.x=point[i+1].y-point[i].y;
    tt.y=point[i].x-point[i+1].x;
    dl k=r/sqrt(tt.x*tt.x+tt.y*tt.y);
    tt.x*=k;tt.y*=k;
    ta.x=point[i].x+tt.x;
    ta.y=point[i].y+tt.y;
    tb.x=point[i+1].x+tt.x;
    tb.y=point[i+1].y+tt.y;
        dl a,b,c;
        getline(ta,tb,a,b,c);
        cut(a,b,c);
    }
    return;
}
int main(){
    scanf("%d%lf",&n,&r);
    for(int i=1;i<=n;i++){
    scanf("%lf%lf",&point[i].x,&point[i].y);
    }
    solve();
    int x,y;
    dl res=-1;
    for(int i=1;i<=cnt;i++){
    for(int j=i;j<=cnt;j++){
        dl tmp=dis(p[i],p[j]);
        if(tmp>res){
        res=tmp;
        x=i;
        y=j;
        }
    }
    }
    printf("%.4f %.4f %.4f %.4f\n",p[x].x,p[x].y,p[y].x,p[y].y);
    return 0;
}

 

以上是关于POJ3384:Feng Shui——题解的主要内容,如果未能解决你的问题,请参考以下文章

[poj] 3384 Feng Shui || 半平面交

poj 3384 半平面交

poj.3384Cows(计算几何)(凸包)

poj.3384Cows(计算几何)(凸包)

poj.3384Cows(计算几何)(凸包)

POJ 3384 放地毯半平面交

(c)2006-2024 SYSTEM All Rights Reserved IT常识