记录编号 |
367125 |
评测结果 |
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |
题目名称 |
大灾变 |
最终得分 |
100 |
用户昵称 |
FoolMike |
是否通过 |
通过 |
代码语言 |
C++ |
运行时间 |
1.927 s |
提交时间 |
2017-01-28 16:35:15 |
内存使用 |
46.07 MiB |
显示代码纯文本
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
typedef double db;
const int N=1e6+10;
const db eps=1e-6;
int n,tail;
struct pt{
db x,y;
pt operator + (const pt &a)const{return (pt){x+a.x,y+a.y};}
pt operator - (const pt &a)const{return (pt){x-a.x,y-a.y};}
db operator ^ (const pt &a)const{return x*a.y-y*a.x;}
bool operator < (const pt &a)const{return x==a.x?y>a.y:x<a.x;}
}p[N],a[N],q[N],ans1,ans2;
db check(pt &x,pt &y,pt &z){//x到y到z转角是顺时针还是逆时针
return (y-x)^(z-x);
}
pt getline(pt x,pt y){//返回斜截式
db k=(x.y-y.y)/(x.x-y.x);
return (pt){k,x.y-k*x.x};
}
pt point(pt &x,pt &y){//返回交点坐标
db k=-(x.y-y.y)/(x.x-y.x);
return (pt){k,x.y+k*x.x};
}
int main()
{
freopen("cataclysm.in","r",stdin);
freopen("cataclysm.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%lf%lf",&p[i].x,&p[i].y);
sort(p+1,p+n+1);
for (int i=1;i<n;i++) a[i]=getline(p[i],p[i+1]);
a[0].x=-1e30;
a[n]=getline(p[1],p[1]+(pt){-eps,1e6});//相当于垂直于x轴的直线,防止越界
a[n+1]=getline(p[n],p[n]+(pt){eps,1e6});
sort(a,a+n+2);
//构造半平面交的凸包
for (int i=1;i<=n+1;i++)
if (abs(a[i].x-a[i-1].x)>eps){//筛掉斜率一样的直线
for (;1<tail&&check(q[tail-1],q[tail],a[i])>=0;tail--);
q[++tail]=a[i];
}
db now=ans1.y=ans2.y=1e30;
for (int i=1,j=1;i<tail;i++){
pt tmp=point(q[i],q[i+1]);
if (ans2.y>eps&&tmp.y<ans2.y) ans2=tmp;
for (;j<=n&&p[j].x<=tmp.x;j++){
if (now>eps&&p[j].x*q[i].x+q[i].y-p[j].y<now)
now=p[j].x*q[i].x+q[i].y-p[j].y,ans1=(pt){p[j].x,now+p[j].y};
}
if (j<=n&&j>1){
pt tmp2=getline(p[j-1],p[j]);
if (now>eps&&tmp.y-(tmp.x*tmp2.x+tmp2.y)<now)
now=tmp.y-(tmp.x*tmp2.x+tmp2.y),ans1=tmp;
}
}
if (abs(ans1.x)<=eps) ans1.x=0;
if (abs(ans1.y)<=eps) ans1.y=0;
if (abs(ans2.x)<=eps) ans2.x=0;
if (abs(ans2.y)<=eps) ans2.y=0;
printf("%.2lf %.2lf\n",ans1.x,ans1.y);
printf("%.2lf %.2lf\n",ans2.x,ans2.y);
return 0;
}