hdu2823 2010.3.6
The widest road
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 72 Accepted Submission(s): 13
Problem Description
There were two families in the village —family A and family B, while these two families didn’t get along well with eachother. Now the head of the village decided to make a road through the villageand it must be straight, for a straight line makes the way shortest andmeanwhile, saves the cost. At that time, the heads of the two familiesproposed, because they didn’t want their own families live separated along thetwo sides of the road, thus it might decrease the solidarity of family. Besides,the two families were antipathetic to each other; neither wanted to livetogether with the other in a same side of the road. Then it made the villagehead in a pickle, he hoped the road to be as wide as possible. So what’s thepossible maximal width of this road?
In order to simplify the problem, let’sregard the living place of each family member is just a point.
Input
There are several test cases in the input.
The first line of each input contains n andm (1 ≤ m,n ≤ 1000). As for the following n lines, there are two numbers in everyline, representing the living places of A family members. And the following mlines represent the living places of B family members.
Output
The output numbers of each line are themaximal width of the road (retain four decimal), while if it’s impossible tomake such a road, then just output 0.0000.
Sample Input
3 3
0.0 0.0
1.0 0.0
0.0 1.0
4.0 0.0
5.0 0.0
4.0 1.0
Sample Output
3.0000
Source
2009 Multi-University Training Contest 1 -Host by TJU
Recommend
gaojie
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define eps 1e-8
#define zero(x) (((x)>0?(x):-(x))<eps)
#define _sign(x) ((x)>eps?1:((x)<-eps?2:0))
struct point{double x,y;};
//计算cross product (P1-P0)x(P2-P0)
double xmult(point p1,point p2,point p0){
return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
//graham算法顺时针构造包含所有共线点的凸包,O(nlogn)
point p1,p2;
int graham_cp(const void* a,const void* b){
double ret=xmult(*((point*)a),*((point*)b),p1);
return zero(ret)?(xmult(*((point*)a),*((point*)b),p2)>0?1:-1):(ret>0?1:-1);
}
void _graham(int n,point* p,int& s,point* ch){
int i,k=0;
for (p1=p2=p[0],i=1;i<n;p2.x+=p[i].x,p2.y+=p[i].y,i++)
if (p1.y-p[i].y>eps||(zero(p1.y-p[i].y)&&p1.x>p[i].x))
p1=p[k=i];
p2.x/=n,p2.y/=n;
p[k]=p[0],p[0]=p1;
qsort(p+1,n-1,sizeof(point),graham_cp);
for (ch[0]=p[0],ch[1]=p[1],ch[2]=p[2],s=i=3;i<n;ch[s++]=p[i++])
for (;s>2&&xmult(ch[s-2],p[i],ch[s-1])<-eps;s--);
}
//构造凸包接口函数,传入原始点集大小n,点集p(p原有顺序被打乱!)
//返回凸包大小,凸包的点在convex中
//参数maxsize为1包含共线点,为0不包含共线点,缺省为1
//参数clockwise为1顺时针构造,为0逆时针构造,缺省为1
//在输入仅有若干共线点时算法不稳定,可能有此类情况请另行处理!
//不能去掉点集中重合的点
int graham(int n,point* p,point* convex,int maxsize=1,int dir=1){
point* temp=new point[n];
int s,i;
_graham(n,p,s,temp);
for (convex[0]=temp[0],n=1,i=(dir?1:(s-1));dir?(i<s):i;i+=(dir?1:-1))
if (maxsize||!zero(xmult(temp[i-1],temp[i],temp[(i+1)%s])))
convex[n++]=temp[i];
delete []temp;
return n;
}
//两点距离
double distance(point p1,point p2){
return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}
//点到线段距离
double disptoseg(point p,point l1,point l2){
point t=p;
t.x+=l1.y-l2.y,t.y+=l2.x-l1.x;
if (xmult(l1,t,p)*xmult(l2,t,p)>eps)
return distance(p,l1)<distance(p,l2)?distance(p,l1):distance(p,l2);
return fabs(xmult(p,l1,l2))/distance(l1,l2);
}
//判三点共线
int dots_inline(point p1,point p2,point p3){
return zero(xmult(p1,p2,p3));
}
//判两点在线段同侧,点在线段上返回0
int same_side(point p1,point p2,point l1,point l2){
return xmult(l1,p1,l2)*xmult(l1,p2,l2)>eps;
}
//判点是否在线段上,包括端点
int dot_online_in(point p,point l1,point l2){
return zero(xmult(p,l1,l2))&&(l1.x-p.x)*(l2.x-p.x)<eps&&(l1.y-p.y)*(l2.y-p.y)<eps;
}
//判两线段相交,包括端点和部分重合
int intersect_in(point u1,point u2,point v1,point v2){
if (!dots_inline(u1,u2,v1)||!dots_inline(u1,u2,v2))
return !same_side(u1,u2,v1,v2)&&!same_side(v1,v2,u1,u2);
return dot_online_in(u1,v1,v2)||dot_online_in(u2,v1,v2)||dot_online_in(v1,u1,u2)||dot_online_in(v2,u1,u2);
}
//判点在凸多边形内或多边形边上,顶点按顺时针或逆时针给出
int inside_convex(point q,int n,point* p){
int i,s[3]={1,1,1};
for (i=0;i<n&&s[1]|s[2];i++)
s[_sign(xmult(p[(i+1)%n],q,p[i]))]=0;
return s[1]|s[2];
}
void solve(int a,int b,point ca[],point cb[])
{
double tmp,ret;
if(a==1&&b==1){
printf("%.4lf\n",distance(ca[0],cb[0]));
return;
}
if(a==1&&b==2){
printf("%.4lf\n",disptoseg(ca[0],cb[0],cb[1]));
return;
}
if(a==2&&b==1){
printf("%.4lf\n",disptoseg(cb[0],ca[0],ca[1]));
return;
}
if(a==2&&b==2){
if(intersect_in(ca[0],ca[1],cb[0],cb[1])==1){
printf("0.0000\n");
return;
}
ret=1000000000;
tmp=disptoseg(ca[0],cb[0],cb[1]);
if(tmp<ret)
ret=tmp;
tmp=disptoseg(ca[1],cb[0],cb[1]);
if(tmp<ret)
ret=tmp;
tmp=disptoseg(cb[0],ca[0],ca[1]);
if(tmp<ret)
ret=tmp;
tmp=disptoseg(cb[1],ca[0],ca[1]);
if(tmp<ret)
ret=tmp;
printf("%.4lf\n",ret);
return;
}
if(a==1&&b>=3){
if(inside_convex(ca[0],b,cb)==1){
printf("0.0000\n");
return;
}
ret=1000000000;
for(int i=0;i<b-1;i++){
tmp=disptoseg(ca[0],cb[i],cb[i+1]);
if(tmp<ret)
ret=tmp;
}
tmp=disptoseg(ca[0],cb[0],cb[b-1]);
if(tmp<ret)
ret=tmp;
printf("%.4lf\n",ret);
return;
}
if(a>=3&&b==1){
if(inside_convex(cb[0],a,ca)==1){
printf("0.0000\n");
return;
}
ret=1000000000;
for(int i=0;i<a-1;i++){
tmp=disptoseg(cb[0],ca[i],ca[i+1]);
if(tmp<ret)
ret=tmp;
}
tmp=disptoseg(cb[0],ca[0],ca[a-1]);
if(tmp<ret)
ret=tmp;
printf("%.4lf\n",ret);
return;
}
if(a==2&&b>=3){
if(inside_convex(ca[0],b,cb)==1||inside_convex(ca[1],b,cb)==1){
printf("0.0000\n");
return;
}
for(int i=0;i<b-1;i++){
if(intersect_in(ca[0],ca[1],cb[i],cb[i+1])==1){
printf("0.0000\n");
return;
}
}
if(intersect_in(ca[0],ca[1],cb[0],cb[b-1])==1){
printf("0.0000\n");
return;
}
ret=1000000000;
for(int i=0;i<a;i++){
for(int j=0;j<b-1;j++){
tmp=disptoseg(ca[i],cb[j],cb[j+1]);
if(tmp<ret)
ret=tmp;
}
tmp=disptoseg(ca[i],cb[0],cb[b-1]);
if(tmp<ret)
ret=tmp;
}
for(int i=0;i<b;i++){
for(int j=0;j<a-1;j++){
tmp=disptoseg(cb[i],ca[j],ca[j+1]);
if(tmp<ret)
ret=tmp;
}
tmp=disptoseg(cb[i],ca[0],ca[a-1]);
if(tmp<ret)
ret=tmp;
}
printf("%.4lf\n",ret);
return;
}
if(a>=3&&b==2){
if(inside_convex(cb[0],a,ca)==1||inside_convex(cb[1],a,ca)==1){
printf("0.0000\n");
return;
}
for(int i=0;i<a-1;i++){
if(intersect_in(cb[0],cb[1],ca[i],ca[i+1])==1){
printf("0.0000\n");
return;
}
}
if(intersect_in(cb[0],cb[1],ca[0],ca[a-1])==1){
printf("0.0000\n");
return;
}
ret=1000000000;
for(int i=0;i<a;i++){
for(int j=0;j<b-1;j++){
tmp=disptoseg(ca[i],cb[j],cb[j+1]);
if(tmp<ret)
ret=tmp;
}
tmp=disptoseg(ca[i],cb[0],cb[b-1]);
if(tmp<ret)
ret=tmp;
}
for(int i=0;i<b;i++){
for(int j=0;j<a-1;j++){
tmp=disptoseg(cb[i],ca[j],ca[j+1]);
if(tmp<ret)
ret=tmp;
}
tmp=disptoseg(cb[i],ca[0],ca[a-1]);
if(tmp<ret)
ret=tmp;
}
printf("%.4lf\n",ret);
return;
}
if(a>=3&&b>=3){
for(int i=0;i<a;i++){
if(inside_convex(ca[i],b,cb)==1){
printf("0.0000\n");
return;
}
}
for(int i=0;i<b;i++){
if(inside_convex(cb[i],a,ca)==1){
printf("0.0000\n");
return;
}
}
for(int i=0;i<a-1;i++){
for(int j=0;j<b-1;j++){
if(intersect_in(ca[i],ca[i+1],cb[j],cb[j+1])==1){
printf("0.0000\n");
return;
}
}
if(intersect_in(ca[i],ca[i+1],cb[0],cb[b-1])==1){
printf("0.0000\n");
return;
}
}
for(int i=0;i<b-1;i++){
if(intersect_in(ca[0],ca[a-1],cb[i],cb[i+1])==1){
printf("0.0000\n");
return;
}
}
if(intersect_in(ca[0],ca[a-1],cb[0],cb[b-1])==1){
printf("0.0000\n");
return;
}
ret=1000000000;
for(int i=0;i<a;i++){
for(int j=0;j<b-1;j++){
tmp=disptoseg(ca[i],cb[j],cb[j+1]);
if(tmp<ret)
ret=tmp;
}
tmp=disptoseg(ca[i],cb[0],cb[b-1]);
if(tmp<ret)
ret=tmp;
}
for(int i=0;i<b;i++){
for(int j=0;j<a-1;j++){
tmp=disptoseg(cb[i],ca[j],ca[j+1]);
if(tmp<ret)
ret=tmp;
}
tmp=disptoseg(cb[i],ca[0],ca[b-1]);
if(tmp<ret)
ret=tmp;
}
printf("%.4lf\n",ret);
return;
}
}
int main()
{
int n,m,a,b;
point pa[1005],pb[1005],ca[1005],cb[1005];
while(scanf("%d%d",&n,&m)!=EOF){
for(int i=0;i<n;i++)
scanf("%lf%lf",&pa[i].x,&pa[i].y);
for(int i=0;i<m;i++)
scanf("%lf%lf",&pb[i].x,&pb[i].y);
if(n<3){
for(int i=0;i<n;i++)
ca[i]=pa[i];
a=n;
}
if(m<3){
for(int i=0;i<m;i++)
cb[i]=pb[i];
b=m;
}
if(n>=3){
a=graham(n,pa,ca,0);
if(a==1){
ca[a]=pa[a];
a++;
}
}
if(m>=3){
b=graham(m,pb,cb,0);
if(b==1){
cb[b]=pb[b];
b++;
}
}
solve(a,b,ca,cb);
}
return 0;
}