poj3608(两凸包间最小距离->旋转卡壳)

这题算法十分诡异。。只是抄了个板子还是不能够很好地理解。。tm都不敢说是原创的了。。。

这个是取了A凸包的最低点和B凸包的最高点,作用。。。个人感觉就是保证第一次找的时候是最近点,以便后续进行下去。。然后在A凸包上找点,在B凸包上找边,枚举边,然后在A凸包逆时针找最近点。。由于B凸包边的枚举顺序也是逆时针,所以可以分开枚举。。然后复杂度就降到O(n)了。。

更具体的可以去百度。。毕竟窝也挺迷的。。




#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<cmath>
#include<stack>
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,l,r) for(int i=l;i>=r;i--)
#define link(x) for(edge *j=h[x];j;j=j->next)
#define inf 10000
#define mem(a) memset(a,0,sizeof(a))
#define ll long long
#define eps 1e-8
#define succ(x) (1<<x)
#define lowbit(x) (x&(-x))
#define sqr(x) ((x)*(x))
#define mid (x+y>>1)
#define NM 100005
#define nm 100498
#define pi 3.1415926535897931
using namespace std;
ll read(){
    ll x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return f*x;
}











struct P{
	double x,y;
	P(double x=0,double y=0):x(x),y(y){}
	P operator-(const P&o){return P(x-o.x,y-o.y);}
	double operator*(const P&o){return x*o.y-y*o.x;}
	double operator%(const P&o){return x*o.x+y*o.y;}
}a[NM],b[NM];
double dis(P o){return sqrt(sqr(o.x)+sqr(o.y));}
int n,m;
double ans;

double getd(P a,P b,P c){
	if((b-c)%(a-c)<-eps)return dis(a-c);
	if((c-b)%(a-b)<-eps)return dis(a-b);
	return fabs((a-b)*(c-b))/dis(b-c);
}

double lined(P a,P b,P c,P d){return min(min(getd(a,c,d),getd(b,c,d)),min(getd(c,a,b),getd(d,a,b)));}

void rorate(P a[],P b[],int n,int m){
	int i=1,j=1,tmp;
	a[n+1]=a[i];b[m+1]=b[1];
	inc(k,1,n)if(a[k].y<a[i].y)i=k;
	inc(k,1,m)if(b[k].y>b[j].y)j=k;
	inc(k,1,n){
		while(tmp=(b[j+1]-a[i])*(a[i+1]-a[i])-(b[j]-a[i])*(a[i+1]-a[i])>eps)j=j%m+1;
		if(tmp<-eps)ans=min(ans,getd(b[j],a[i],a[i+1]));
		else ans=min(ans,lined(b[j],b[j+1],a[i],a[i+1]));
		//printf("%lf\n",ans);
		i=i%n+1;
	}
}

int main(){
	//freopen("data.in","r",stdin);
	while(n=read()){
		m=read();ans=inf;
		dec(i,n,1)scanf("%lf%lf",&a[i].x,&a[i].y);
		dec(i,m,1)scanf("%lf%lf",&b[i].x,&b[i].y);
		rorate(a,b,n,m);
		rorate(b,a,m,n);
		printf("%lf\n",ans);
	}
	return 0;
}






Bridge Across Islands
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 11544 Accepted: 3400 Special Judge

Description

Thousands of thousands years ago there was a small kingdom located in the middle of the Pacific Ocean. The territory of the kingdom consists two separated islands. Due to the impact of the ocean current, the shapes of both the islands became convex polygons. The king of the kingdom wanted to establish a bridge to connect the two islands. To minimize the cost, the king asked you, the bishop, to find the minimal distance between the boundaries of the two islands.

Input

The input consists of several test cases.
Each test case begins with two integers N, M. (3 ≤ N, M ≤ 10000)
Each of the next N lines contains a pair of coordinates, which describes the position of a vertex in one convex polygon.
Each of the next M lines contains a pair of coordinates, which describes the position of a vertex in the other convex polygon.
A line with N = M = 0 indicates the end of input.
The coordinates are within the range [-10000, 10000].

Output

For each test case output the minimal distance. An error within 0.001 is acceptable.

Sample Input

4 4
0.00000 0.00000
0.00000 1.00000
1.00000 1.00000
1.00000 0.00000
2.00000 0.00000
2.00000 1.00000
3.00000 1.00000
3.00000 0.00000
0 0

Sample Output

1.00000

Source

[Submit]   [Go Back]   [Status]   [Discuss]


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值