zoukankan      html  css  js  c++  java
  • POJ 3384 Feng Shui (半平面交)

    Feng Shui
    Time Limit: 2000MS   Memory Limit: 65536K
    Total Submissions: 3743   Accepted: 1150   Special Judge

    Description

    Feng shui is the ancient Chinese practice of placement and arrangement of space to achieve harmony with the environment. George has recently got interested in it, and now wants to apply it to his home and bring harmony to it.

    There is a practice which says that bare floor is bad for living area since spiritual energy drains through it, so George purchased two similar round-shaped carpets (feng shui says that straight lines and sharp corners must be avoided). Unfortunately, he is unable to cover the floor entirely since the room has shape of a convex polygon. But he still wants to minimize the uncovered area by selecting the best placing for his carpets, and asks you to help.

    You need to place two carpets in the room so that the total area covered by both carpets is maximal possible. The carpets may overlap, but they may not be cut or folded (including cutting or folding along the floor border) — feng shui tells to avoid straight lines.

    Input

    The first line of the input file contains two integer numbers n and r — the number of corners in George’s room (3 ≤ n ≤ 100) and the radius of the carpets (1 ≤ r ≤ 1000, both carpets have the same radius). The following n lines contain two integers xi and yi each — coordinates of the i-th corner (−1000 ≤ xiyi ≤ 1000). Coordinates of all corners are different, and adjacent walls of the room are not collinear. The corners are listed in clockwise order.

    Output

    Write four numbers x1y1x2y2 to the output file, where (x1y1) and (x2y2) denote the spots where carpet centers should be placed. Coordinates must be precise up to 4 digits after the decimal point.

    If there are multiple optimal placements available, return any of them. The input data guarantees that at least one solution exists.

    Sample Input

    #1 5 2
    -2 0
    -5 3
    0 8
    7 3
    5 0
    #2 4 3
    0 0
    0 8
    10 8
    10 0

    Sample Output

    #1 -2 3 3 2.5
    #2 3 5 7 3

    Hint

    Source

    Northeastern Europe 2006, Northern Subregion

    给你两个圆,半径相等,求放在一个凸多边形里两个圆不碰到边界的圆心。两个圆是可以重叠的。

    半平面交,向内推进R,然后求组成多边形的最远的两个点即可。

      1 /* ***********************************************
      2 Author        :kuangbin
      3 Created Time  :2013/8/18 15:52:28
      4 File Name     :F:2013ACM练习专题学习计算几何半平面交POJ3384.cpp
      5 ************************************************ */
      6 
      7 #include <stdio.h>
      8 #include <string.h>
      9 #include <iostream>
     10 #include <algorithm>
     11 #include <vector>
     12 #include <queue>
     13 #include <set>
     14 #include <map>
     15 #include <string>
     16 #include <math.h>
     17 #include <stdlib.h>
     18 #include <time.h>
     19 using namespace std;
     20 const double eps = 1e-8;
     21 const double PI = acos(-1.0);
     22 int sgn(double x)
     23 {
     24     if(fabs(x) < eps) return 0;
     25     if(x < 0) return -1;
     26     else return 1;
     27 }
     28 struct Point
     29 {
     30     double x,y;
     31     Point(){}
     32     Point(double _x,double _y)
     33     {
     34         x = _x; y = _y;
     35     }
     36     Point operator -(const Point &b)const
     37     {
     38         return Point(x - b.x, y - b.y);
     39     }
     40     double operator ^(const Point &b)const
     41     {
     42         return x*b.y - y*b.x;
     43     }
     44     double operator *(const Point &b)const
     45     {
     46         return x*b.x + y*b.y;
     47     }
     48 };
     49 struct Line
     50 {
     51     Point s,e;
     52     double k;
     53     Line(){}
     54     Line(Point _s,Point _e)
     55     {
     56         s = _s; e = _e;
     57         k = atan2(e.y - s.y,e.x - s.x);
     58     }
     59     Point operator &(const Line &b)const
     60     {
     61         Point res = s;
     62         double t = ((s - b.s)^(b.s - b.e))/((s - e)^(b.s - b.e));
     63         res.x += (e.x - s.x)*t;
     64         res.y += (e.y - s.y)*t;
     65         return res;
     66     }
     67 };
     68 //半平面交,直线的左边代表有效区域
     69 bool HPIcmp(Line a,Line b)
     70 {
     71     if(fabs(a.k - b.k) > eps)return a.k < b.k;
     72     return ((a.s - b.s)^(b.e - b.s)) < 0;
     73 }
     74 Line Q[1010];
     75 void HPI(Line line[], int n, Point res[], int &resn)
     76 {
     77     int tot = n;
     78     sort(line,line+n,HPIcmp);
     79     tot = 1;
     80     for(int i = 1;i < n;i++)
     81         if(fabs(line[i].k - line[i-1].k) > eps)
     82             line[tot++] = line[i];
     83     int head = 0, tail = 1;
     84     Q[0] = line[0];
     85     Q[1] = line[1];
     86     resn = 0;
     87     for(int i = 2; i < tot; i++)
     88     {
     89         if(fabs((Q[tail].e-Q[tail].s)^(Q[tail-1].e-Q[tail-1].s)) < eps || fabs((Q[head].e-Q[head].s)^(Q[head+1].e-Q[head+1].s)) < eps)
     90             return;
     91         while(head < tail && (((Q[tail]&Q[tail-1]) - line[i].s)^(line[i].e-line[i].s)) > eps)
     92             tail--;
     93         while(head < tail && (((Q[head]&Q[head+1]) - line[i].s)^(line[i].e-line[i].s)) > eps)
     94             head++;
     95         Q[++tail] = line[i];
     96     }
     97     while(head < tail && (((Q[tail]&Q[tail-1]) - Q[head].s)^(Q[head].e-Q[head].s)) > eps)
     98         tail--;
     99     while(head < tail && (((Q[head]&Q[head-1]) - Q[tail].s)^(Q[tail].e-Q[tail].e)) > eps)
    100         head++;
    101     if(tail <= head + 1)return;
    102     for(int i = head; i < tail; i++)
    103         res[resn++] = Q[i]&Q[i+1];
    104     if(head < tail - 1)
    105         res[resn++] = Q[head]&Q[tail];
    106 }
    107 Point p[1010];
    108 Line line[1010];
    109 //*两点间距离
    110 double dist(Point a,Point b)
    111 {
    112     return sqrt((a-b)*(a-b));
    113 }
    114 void change(Point a,Point b,Point &c,Point &d,double p)//将线段ab往左移动距离p
    115 {
    116     double len = dist(a,b);
    117     double dx = (a.y - b.y)*p/len;
    118     double dy = (b.x - a.x)*p/len;
    119     c.x = a.x + dx; c.y = a.y + dy;
    120     d.x = b.x + dx; d.y = b.y + dy;
    121 }
    122 int main()
    123 {
    124     //freopen("in.txt","r",stdin);
    125     //freopen("out.txt","w",stdout);
    126     int n;
    127     double r;
    128     while(scanf("%d%lf",&n,&r) == 2)
    129     {
    130         for(int i = 0;i < n;i++)
    131             scanf("%lf%lf",&p[i].x,&p[i].y);
    132         reverse(p,p+n);
    133         for(int i = 0;i < n;i++)
    134         {
    135             Point t1,t2;
    136             change(p[i],p[(i+1)%n],t1,t2,r);
    137             line[i] = Line(t1,t2);
    138         }
    139         int resn;
    140         HPI(line,n,p,resn);
    141         int res1 = 0, res2 = 0;
    142         for(int i = 0;i < resn;i++)
    143             for(int j = i;j < resn;j++)
    144                 if(dist(p[i],p[j]) > dist(p[res1],p[res2]))
    145                     res1 = i, res2 = j;
    146         printf("%.5f %.5f %.5f %.5f
    ",p[res1].x,p[res1].y,p[res2].x,p[res2].y);
    147     }
    148     return 0;
    149 }
  • 相关阅读:
    对PostgreSQL的 seq scan , bitmap index scan 和 index scan 的进一步理解
    C# IEnumerable和IEnumerator的区别,如何实现
    老板运煤问题及解决方案
    快速排序和简单排序
    给定数组,查找最小的k个元素或最大的k个元素
    一列数字的规则如下;1,1,2,3,5,8,13,21,34........ 求第30位数字是多少,用递规和非递归两种方法算法实现
    C# 如何利用反射来加载程序集,并调用程序集中有关类的方法
    http 请求 header 应用分析
    templatemonster 10231 面朝大海 你听到什么?
    足球俱乐部 网站模板 附带源文件 字体
  • 原文地址:https://www.cnblogs.com/kuangbin/p/3266097.html
Copyright © 2011-2022 走看看