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

题目链接

题意 : 两个圆能够覆盖的最大多边形面积的时候两个圆圆心的坐标是多少,两个圆必须在多边形内。

思路 : 向内推进r,然后求多边形最远的两个点就是能覆盖的最大面积。

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <iostream>

 using namespace std ;

 struct node
 {
     double x,y ;
 }p[110],temp[110],newp[110];
 int n,newn ;
 double a,b,c,r ;

 void getlinee(node x,node y)
 {
     a = y.y-x.y ;
     b = x.x-y.x ;
     c = y.x*x.y-x.x*y.y ;
 }
 node intersect(node x,node y)
 {
     double u = fabs(a*x.x+b*x.y+c) ;
     double v = fabs(a*y.x+b*y.y+c) ;
     node t ;
     t.x = (x.x*v+y.x*u)/(u+v) ;
     t.y = (x.y*v+y.y*u)/(u+v) ;
     return t ;
 }
 void cut()
 {
     int cutn = 0 ;
     for(int i = 1 ; i <= newn ; i++)
    {
        if(newp[i].x*a+newp[i].y*b+c >= 0)
            temp[++cutn] = newp[i] ;
        else
        {
            if(newp[i-1].x*a+newp[i-1].y*b+c > 0)
                temp[++cutn] = intersect(newp[i-1],newp[i]) ;
            if(newp[i+1].x*a+newp[i+1].y*b+c > 0)
                temp[++cutn] = intersect(newp[i+1],newp[i]) ;
        }
    }
    for(int i = 1 ; i <= cutn ; i++)
        newp[i] = temp[i] ;
    newp[cutn+1] = newp[1] ;
    newp[0] = newp[cutn] ;
    newn = cutn ;
    //printf("newn%d = %d\n",cnt++,newn) ;
 }
 void solve()
 {
     for(int i = 1 ; i <= n ; i ++)
    {
        newp[i] = p[i] ;
    }
    newp[n+1] = p[1] ;
    newp[0] = p[n] ;
    newn = n ;
    for(int i = 1 ; i <= n ; i++)
    {
        node t,t1,t2 ;
        t.x = p[i+1].y-p[i].y ;
        t.y = p[i].x-p[i+1].x ;
        double k = r/sqrt(t.x*t.x+t.y*t.y) ;
        t.x *= k ;
        t.y *= k ;
        t1.x = t.x+p[i].x ;
        t1.y = t.y+p[i].y ;
        t2.x = t.x+p[i+1].x ;
        t2.y = t.y+p[i+1].y ;
        getlinee(t1,t2) ;
        cut() ;
    }
 }
 int main()
 {
     while(~scanf("%d %lf",&n,&r))
    {
        for(int i = 1 ; i <= n ; i++)
            scanf("%lf %lf",&p[i].x,&p[i].y) ;
        p[n+1] = p[1] ;
        solve() ;
        int t1 = 0,t2 = 0 ;
        double maxx = 0.0 ;
        for(int i = 1 ; i <= newn ; i++)
        {
            for(int j = i+1 ; j <= newn ; j++)
            {
                double dis = sqrt((newp[i].x-newp[j].x)*(newp[i].x-newp[j].x)+(newp[i].y-newp[j].y)*(newp[i].y-newp[j].y)) ;
                if(dis > maxx)
                {
                    maxx = dis ;
                    t1 = i ;
                    t2 = j ;
                }
            }
        }
        printf("%.4lf %.4lf %.4lf %.4lf\n",newp[t1].x,newp[t1].y,newp[t2].x,newp[t2].y) ;
    }
     return 0 ;
 }

时间: 2024-10-07 17:54:42

POJ 3384 Feng Shui(半平面交向内推进求最远点对)的相关文章

poj 3384 Feng Shui 半平面交的应用 求最多覆盖凸多边形的面积的两个圆 的圆心坐标

题目来源: http://poj.org/problem?id=3384 分析: 用半平面交将多边形的每条边一起向"内"推进R,得到新的多边形(半平面交),然后求多边形的最远两点. 代码如下: const double EPS = 1e-10; const int Max_N = 105 ; struct Point{ double x,y; Point(){} Point(double x, double y):x(x),y(y){} Point operator - (Point

POJ 3384 Feng Shui [半平面交]

Feng Shui Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 5537   Accepted: 1663   Special Judge Description Feng shui is the ancient Chinese practice of placement and arrangement of space to achieve harmony with the environment. George h

POJ 3525 Most Distant Point from the Sea (半平面交向内推进+二分半径)

题目链接 题意 : 给你一个多边形,问你里边能够盛的下的最大的圆的半径是多少. 思路 :先二分半径r,半平面交向内推进r.模板题 1 #include <stdio.h> 2 #include <string.h> 3 #include <iostream> 4 #include <math.h> 5 const double eps = 1e-10 ; 6 7 using namespace std ; 8 9 struct node 10 { 11 do

POJ 3384 Feng Shui --直线切平面

题意:房间是一个凸多边形,要在里面铺设两条半径为r的圆形地毯,可以重叠,现在要求分别铺设到哪,使地毯所占的地面面积最大. 解法:要使圆形地毯所占面积最大,圆形地毯一定是与边相切的,这样才能使尽量不重叠. 那么我们把所有边都向内推进r,那么形成的多边形,可知两个圆形地毯的中心就一定在这个多边形边界上,最优的情况下是在此新凸包的最远点对上. 初始多边形为(-1000,-1000)到(1000,1000)的矩形,那么我们可以模拟把每条边都推进,每次切出新的凸多边形,然后得出最后的凸多边形,然后n^2枚

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<c

POJ 1279 Art Gallery 半平面交求多边形核

第一道半平面交,只会写N^2. 将每条边化作一个不等式,ax+by+c>0,所以要固定顺序,方便求解. 半平面交其实就是对一系列的不等式组进行求解可行解. 如果某点在直线右侧,说明那个点在区域内,否则出现在左边,就可能会有交点,将交点求出加入. //#pragma comment(linker, "/STACK:16777216") //for c++ Compiler #include <stdio.h> #include <iostream> #inc

POJ 2451 nlog(n)半平面交裸题。

前言       最近学习C#,不过好在当初考计算机二级学习过C++,刚上手没有对C#感到很恐惧.C#视频也看了几天 了,总感觉不总结一下心里没底,现在跟着我从头走进C#之旅吧.     C#是以后总面向对象的编程语言(OOP),C#是从C和C++派生出来的,主要用于开发可以运行在.NET平台 上的应用程序.随着.NET的发展,C#语言简单.现代.面向对象和类型安全显示了一定的优势.     下面我就介绍一些初学者不太理解的一些东西.   C#有以下突出的特点       (1)语法简洁.不允许

【模板】凸包向内推进求不严格的半平面交——poj3384

想不明白这题写严格的半平面交为什么会错 /* 凸包所有边向内推进r */ #include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<vector> #include<algorithm> #include<queue> using namespace std; #define N 205 typedef double db;

POJ 1474 Video Surveillance 半平面交求多边形是否有核

裸的半平面交求多边形是否有核. 多边形的核: 在多边形核上的点可以看到多边形的所有顶点,凸多边形的核显然就是多边形本身. 多边形的核是一个凸包,对多边形的所有边都做向着多边形的半平面交在判断一下是否构成凸包就可以了 一样的题目还有POJ3335 Video Surveillance Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 3438   Accepted: 1523 Description A friend of y