hdu 2440 Watch out the Animal acm

来源:互联网 发布:windows清理工具 编辑:程序博客网 时间:2024/06/05 22:29

题目:动物园有很多休息点,如果动物冲过保护站点间的线段到外面去就会失踪,现在想建立一个站点是他到休息点的距离和最小,求这个最小的距离和。

分析:计算几何、凸包、费马点、随机。首先,只有凸包的顶点是有意义的休息站;然后,找到到凸包的费马点即可。这里使用随即增量迭代求解。由于具有单调性,所以随机取一个凸包内的点(这里选择凸包的基准点),然后控制步长不断缩短,在随机方向上运动不断迭代到精度满足即可。

#include <algorithm> #include <iostream>#include <cstdlib>#include <cstdio>#include <cmath>#include <ctime>using namespace std;typedef struct pnode{double x,y,d;pnode( double a, double b ) {x = a;y = b;}pnode(){};}point;point Pn,P[105];//两点间距离 double dist( point a, point b ){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}//点到直线距离 double dist( point p, int N ){double sum = 0.0;for ( int i = 0 ; i <= N ; ++ i )sum += dist( p, P[i] );return sum;}//叉乘 ab*ac double crossproduct( point a, point b, point c ){return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);}//坐标排序 bool cmp1( point a, point b ){if ( a.x == b.x ) return a.y < b.y;else return a.x < b.x;}//级角排序 bool cmp2( point a, point b ){return crossproduct( P[0], a, b ) > 0;}//保留去边和回边上的所有点 bool cmp3( point a, point b ){double cp = crossproduct( P[0], a, b );if ( cp == 0 ) {if ( crossproduct( P[0], a, Pn ) == 0 )return a.d > b.d;else return a.d < b.d;}else return cp > 0;}double Graham( int N ){sort( P+0, P+N, cmp1 );sort( P+1, P+N, cmp2 );for ( int i = 1 ; i < N ; ++ i )P[i].d = dist( P[0], P[i] );Pn = P[N-1];sort( P+1, P+N, cmp3 );int top = N;if ( N > 2 ) {top = 2;for ( int i = 3 ; i < N ; ++ i ) {while ( top > 0 && crossproduct( P[top-1], P[top], P[i] ) <= 0 ) -- top;P[++ top] = P[i];}P[++ top] = P[0];//删掉共线的点 int now = 1;for ( int i = 2 ; i <= top ; ++ i ) {if ( crossproduct( P[now-1], P[now], P[i] ) == 0 )P[now] = P[i];else P[++ now] = P[i];}top = now-1; }//随机增量逼近point  t,s = P[0];double sp  = 10000.0,esp = 0.01;double temp,min = dist( s, top );while ( sp > esp ) {int flag = 0;for ( int i = 0 ; i < 10 ; ++ i ) {t = s;int R = rand()%361;t.x += sp*cos(R);t.y += sp*sin(R);temp = dist( t, top );if ( min > temp ) {min = temp;s = t;flag = 1;}}if ( !flag ) sp /= 2.0;}return min;}int main(){srand( time(NULL) );int T,N;while ( scanf("%d",&T) != EOF ) while ( T -- ) {scanf("%d",&N);for ( int i = 0 ; i < N ; ++ i )scanf("%lf%lf",&P[i].x,&P[i].y);printf("%.0lf\n",Graham( N ));if ( T ) printf("\n");}return 0;}



原创粉丝点击