我发现,做题最痛苦的就是读不懂题,比这更痛苦的是,上网搜题意竟然还是错的,纠结啊。。。。。。唉,看了N个解题报告,终于明白了题目的意思,就是有一只青蛙在1号石头上,他要跳到2号石头上,中间可以借助其他石头,一条线路中最长的那段距离作为这条路的代价,求所有路中代价最小的那个。
如果读懂了题这题就很容易做了,刚开始的时候,看了discuss里的一个公式,map[i][j] = min(map[i][j] , max(map[i][k] , map[k][j] ));三重循环直接求出来了。
代码:
View Code
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream> #include <algorithm> #include <math.h> #define N 205 #define INF 100000000 using namespace std ; struct node { int x , y ; }p[N] ; double map[N][N] ; double dis( node a , node b ) { return sqrt( ( double )( ( a.x - b.x ) * ( a.x - b.x ) + ( a.y - b.y ) * ( a.y - b.y ))) ; } int main() { int n , i , j , k ; int c = 1 ; while ( scanf ( "%d" , &n ) , n ) { for ( i = 1 ; i <= n ; i++ ) { scanf ( "%d%d" , &p[i].x , &p[i].y ); } for ( i = 1 ; i <= n ; i++ ) { for ( j = 1 ; j <= n ; j++ ) map[i][j] = INF ; map[i][i] = 0 ; } for ( i = 1 ; i <= n ; i++ ) { for ( j = 1; j < i ; j++ ) { map[i][j] = map[j][i] = dis ( p[i] , p[j] ); } } for ( i = 1 ; i <= n ; i++ ) for ( j = 1 ; j <= n ; j++ ) for ( k = 1 ; k <= n ; k++ ) map[j][k] = min ( map[j][k] , max ( map[j][i] , map[i][k] )) ; printf ( "Scenario #%d\nFrog Distance = %.3f\n\n" , c++ , map[1][2] ); } }
后来读懂了题,感觉有Dijkstra也很好做,就按自己的想法写了一个,由于对Dijkstra的方法理解的不是很深,最后竟然写成了用贪心思想做的,最后又看了一遍Dijkstra,终于还是AC了,也想明白了它的实现原理。
我一直以为,Dijkstra是从一个点开始,搜索所有与它相连的点,找出最短的一条然后再从这个点继续扩展下去,直到目标点。但其实是对于每一个点,都找到与它相连的点判断一下从那个点到它的路径长度是否小于它现在的长度,如果小于就更新,既保持每一个点的dis[i]保存的是从源点到他的最短路,这样到目标点。
由于这道题让求的是所有路中的最大代价,那么dis[i]中存的就是通过i这个点的所有路的最大代价,然后再从最大的那个继续向下扩展。
代码:
View Code
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream> #include <algorithm> #include <math.h> #include <queue> #define N 205 #define INF 10000000 using namespace std ; struct node { int x , y ; }p[N] ; double map[N][N] , d[N] ; int f[N] ; int n , m ; void init( ) { memset( f , 0 , sizeof ( f )) ; f[1] = 1 ; for ( int i = 1 ; i <= n ; i++ ) d[i] = INF ; d[1] = 0 ; } void dijskra( int s ) { int i , j , pos ; double min_t ; memset( f , 0 , sizeof ( f )) ; f[1] = 1 ; for ( i = 1 ; i < n ; i++ ) { min_t = INF ; for ( j = 1 ; j <= n ; j++ ) if ( !f[j] ) { //d[j]中存的是经过j点的所以路的最大代价,若map[j][s] >d[s] 就更新 if ( d[j] > max ( d[s] , map[j][s] )) d[j] = max ( d[s] , map[j][s] ); //找到最大的那个继续向下扩展 if ( d[j] < min_t ) { min_t = d[j] ; pos = j ; } } //如果pos已经是2了,则说明已经找到一条从1到2的路径,它的代价最大 if ( pos == 2 ) return ; s = pos ; f[pos] = 1 ; } } double dis ( node a , node b ) { return sqrt( ( double ) ( ( a.x - b.x ) * ( a.x - b.x ) + ( a.y - b.y ) * ( a.y - b.y ))) ; } int main() { int i , j ; int c = 1 ; while ( scanf ( "%d" , &n ) , n ) { for ( i = 1 ; i <= n ; i++ ) scanf ( "%d%d" , &p[i].x , &p[i].y ) ; //计算两点间的距离 for ( i = 1 ; i <= n ; i++ ) for ( j = 1 ; j < i ; j++ ) map[i][j] = map[j][i] = dis( p[i] , p[j] ); init(); dijskra( 1 ) ; printf ( "Scenario #%d\nFrog Distance = %.3f\n\n" , c++ , d[2] ); } return 0 ; }