坑爹的题,,就是先向内推进r,然后半平面交得出圆心范围。
然后旋转卡壳求最远点对
这道题首先样例给的就不对,不知道什么情况
然后一直WA,后来看了discuss,试了下这组数据:
4 1
0 0
0 2
2 2
2 0
发现n个端点两两距离都一样时会出错,然后改了改代码,就A了
总结就是一直WA的时候,一定要学会看discuss
#include<stdio.h>
#include<algorithm>
#include<math.h>
using namespace std;
const double eps=1e-5;
struct Point {
double x,y;
Point (){}
Point (double xx,double yy) {x=xx;y=yy;}
Point operator -(const Point b)const {return Point(x-b.x,y-b.y);}
double operator ^(const Point b)const {return x*b.y-y*b.x;}
};
struct Line {
Point s,e;
double angle;
Line(){}
Line(Point ss,Point ee) {s=ss;e=ee;}
Point operator &(const Line b)const {
Point res=s;
double t=((s-b.e)^(b.s-b.e))/((s-e)^(b.s-b.e));
res.x+=(e.x-s.x)*t;
res.y+=(e.y-s.y)*t;
return res;
}
};
int n,m;
int r;
Point p[105];
Line l[105],dq[105];
int cmp(Line a,Line b) {
if (fabs(a.angle-b.angle)<eps) return ((a.e-a.s)^(b.s-a.s))>eps;
else return a.angle<b.angle;
}
double dist(Point a,Point b) {
return sqrt((b.x-a.x)*(b.x-a.x)+(b.y-a.y)*(b.y-a.y));
}
void HPI(){
sort(l,l+n,cmp);
int ln;
for(int i=1,j=0;i<n;i++){
if (l[i].angle-l[j].angle>eps) l[++j]=l[i];
ln=j+1;
}
dq[0]=l[0];dq[1]=l[1];
int bot=0,top=1;
//for(int i=0;i<ln;i++) printf("%f %f\n",l[i].s.x,l[i].s.y);
for(int i=2;i<ln;i++) {
while (bot<top && ((l[i].e-l[i].s)^((dq[top]&dq[top-1])-l[i].s))>eps) top--;
while (bot<top && ((l[i].e-l[i].s)^((dq[bot]&dq[bot+1])-l[i].s))>eps) bot++;
dq[++top]=l[i];
}
while (bot<top && ((dq[bot].e-dq[bot].s)^((dq[top]&dq[top-1])-dq[bot].s))>eps) top--;
while (bot<top && ((dq[top].e-dq[top].s)^((dq[bot]&dq[bot+1])-dq[top].s))>eps) bot++;
//for(int i=bot;i<top;i++) printf("%lf %lf\n",dq[i].s.x,dq[i].s.y);
if (top<=bot+1) return;
dq[++top]=dq[bot];
m=0;
for(int i=bot;i<top;i++){
p[m++]=dq[i]&dq[i+1];
//printf("%lf %lf\n",p[m-1].x,p[m-1].y);
}
//方便处理
p[m]=p[0];
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif // ONLINE_JUDGE
while(scanf("%d%d",&n,&r)!=EOF) {
for(int i=0;i<n;i++) scanf("%lf%lf",&p[i].x,&p[i].y);
p[n]=p[0];
for(int i=0;i<n;i++) {
//向内推进r
double dx,dy,len;
Point ta,tb;
ta=p[i];tb=p[i+1];
dx=p[i+1].y-p[i].y;
dy=p[i].x-p[i+1].x;
len=sqrt(dx*dx+dy*dy);
ta.x=p[i].x+dx*r/len;
ta.y=p[i].y+dy*r/len;
tb.x=p[i+1].x+dx*r/len;
tb.y=p[i+1].y+dy*r/len;
l[i].s=ta;
l[i].e=tb;
l[i].angle=atan2(tb.y-ta.y,tb.x-ta.x);
//printf("%f %f\n",l[i].s.x,l[i].s.y);
}
HPI();
//旋转卡壳求最远点对,点逆时针排列
double ans=0;
Point a,b;
//printf("%d\n",m);
for(int i=0,j=1;i<m;i++) {
while(((p[i+1]-p[i])^(p[j]-p[i]))<((p[i+1]-p[i])^(p[j+1]-p[i]))) j=(j+1)%m;
//printf("%f \n",((p[i+1]-p[i])^(p[j]-p[i])));
//printf("%f %f\n",p[i].x,p[i].y);
if (dist(p[i],p[j])>=ans) {
a=p[i];b=p[j];
ans=dist(p[i],p[j]);
}
if (dist(p[i+1],p[j+1])>=ans) {
a=p[i+1];b=p[j+1];
ans=dist(p[i+1],p[j+1]);
}
}
printf("%.4f %.4f %.4f %.4f\n",a.x,a.y,b.x,b.y);
}
return 0;
}