当前位置:编程学习 > C/C++ >>

hdu 2440 Watch out the Animal acm

题目:动物园有很多休息点,如果动物冲过保护站点间的线段到外面去就会失踪,现在想建立一个站点是他到休息点的距离和最小,求这个最小的距离和。
 
分析:计算几何、凸包、费马点、随机。首先,只有凸包的顶点是有意义的休息站;然后,找到到凸包的费马点即可。这里使用随即增量算法逼近求解。由于具有单调性,所以随机取一个凸包内的点(这里选择基准顶点),然后控制步长不断缩短,在随机方向上运动不断逼近到精度满足即可。
 
注意:随机次数的控制,太多会TLE、太少会WA。
 
[cpp]  
#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;  
}  
  
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 ( crossproduct( P[top-1], P[top], P[i] ) < 0 ) -- top;  
            P[++ top] = P[i];  
        }  
        //删掉共线的点   
        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;   
    }  
      
    //随机增量逼近法   
    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;  
}  
 
补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,