​链接​

将边长向内推进r,明显这样把第一个圆的圆心放在新的边长是肯定是最优的,与原本边相切,然后再找新多边上的最远的两点即为两圆心。


poj3384Feng Shui(半平面交)_#includepoj3384Feng Shui(半平面交)_#define_02


1 #include <iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<algorithm>
5 #include<stdlib.h>
6 #include<vector>
7 #include<cmath>
8 #include<queue>
9 #include<set>
10 using namespace std;
11 #define N 2010
12 #define LL long long
13 #define INF 0xfffffff
14 const double eps = 1e-8;
15 const double pi = acos(-1.0);
16 const double inf = ~0u>>2;
17 const int MAXN=1550;
18 int m;
19 double r;
20 int cCnt,curCnt;//此时cCnt为最终切割得到的多边形的顶点数、暂存顶点个数
21 struct point
22 {
23 double x,y;
24 point(double x=0,double y=0):x(x),y(y) {}
25 };
26 typedef point pointt;
27 pointt operator -(point a,point b)
28 {
29 return point(a.x-b.x,a.y-b.y);
30 }
31 point points[MAXN],p[MAXN],q[MAXN];//读入的多边形的顶点(顺时针)、p为存放最终切割得到的多边形顶点的数组、暂存核的顶点
32 void getline(point x,point y,double &a,double &b,double &c) //两点x、y确定一条直线a、b、c为其系数
33 {
34 a = y.y - x.y;
35 b = x.x - y.x;
36 c = y.x * x.y - x.x * y.y;
37 }
38 void initial()
39 {
40 for(int i = 1; i <= m; ++i)p[i] = points[i];
41 p[m+1] = p[1];
42 p[0] = p[m];
43 cCnt = m;//cCnt为最终切割得到的多边形的顶点数,将其初始化为多边形的顶点的个数
44 }
45 point intersect(point x,point y,double a,double b,double c) //求x、y形成的直线与已知直线a、b、c、的交点
46 {
47 double u = fabs(a * x.x + b * x.y + c);
48 double v = fabs(a * y.x + b * y.y + c);
49 point pt;
50 pt.x=(x.x * v + y.x * u) / (u + v);
51 pt.y=(x.y * v + y.y * u) / (u + v);
52 return pt;
53 }
54 void cut(double a,double b ,double c)
55 {
56 curCnt = 0;
57 for(int i = 1; i <= cCnt; ++i)
58 {
59 if(a*p[i].x + b*p[i].y + c >= 0)q[++curCnt] = p[i];// c由于精度问题,可能会偏小,所以有些点本应在右侧而没在,
60 //故应该接着判断
61 else
62 {
63 if(a*p[i-1].x + b*p[i-1].y + c > 0) //如果p[i-1]在直线的右侧的话,
64 {
65 //则将p[i],p[i-1]形成的直线与已知直线的交点作为核的一个顶点(这样的话,由于精度的问题,核的面积可能会有所减少)
66 q[++curCnt] = intersect(p[i],p[i-1],a,b,c);
67 }
68 if(a*p[i+1].x + b*p[i+1].y + c > 0) //原理同上
69 {
70 q[++curCnt] = intersect(p[i],p[i+1],a,b,c);
71 }
72 }
73 }
74 for(int i = 1; i <= curCnt; ++i)p[i] = q[i];//将q中暂存的核的顶点转移到p中
75 p[curCnt+1] = q[1];
76 p[0] = p[curCnt];
77 cCnt = curCnt;
78 }
79 double dis(point a)
80 {
81 return sqrt(a.x*a.x+a.y*a.y);
82 }
83 void solve(int r)
84 {
85 //注意:默认点是顺时针,如果题目不是顺时针,规整化方向
86 initial();
87 for(int i = 1; i <= m; ++i)
88 {
89 point ta, tb, tt;
90 tt.x = points[i+1].y - points[i].y;
91 tt.y = points[i].x - points[i+1].x;
92 double k = r*1.0 / sqrt(tt.x * tt.x + tt.y * tt.y);
93 tt.x = tt.x * k;
94 tt.y = tt.y * k;
95 ta.x = points[i].x + tt.x;
96 ta.y = points[i].y + tt.y;
97 tb.x = points[i+1].x + tt.x;
98 tb.y = points[i+1].y + tt.y;
99 double a,b,c;
100 getline(ta,tb,a,b,c);
101 cut(a,b,c);
102 }
103 double ans = -1;
104 point p1, p2;
105 int i,j;
106 for(i = 1; i <= curCnt ; i++)
107 for(j = i ; j<=curCnt ; j++)
108 {
109 if(ans<dis(p[i]-p[j]))
110 {
111 ans = dis(p[i]-p[j]);
112 p1 = p[i];
113 p2 = p[j];
114 }
115 }
116 printf("%.4f %.4f %.4f %.4f\n",p1.x,p1.y,p2.x,p2.y);
117 }
118 /*void GuiZhengHua(){
119 //规整化方向,逆时针变顺时针,顺时针变逆时针
120 for(int i = 1; i < (m+1)/2; i ++)
121 swap(points[i], points[m-i]);
122 }*/
123 int main()
124 {
125 int r,i;
126 while(scanf("%d%d",&m,&r)!=EOF)
127 {
128 for(i = 1; i <= m ; i++)
129 scanf("%lf%lf",&points[i].x,&points[i].y);
130 points[m+1] = points[1];
131 solve(r);
132 }
133 return 0;
134 }

View Code