poj 1062 昂贵的聘礼
其实这题是昨天做的,不过没来的及写Blog,还有通过这题想通了一些问题,所以想专门的抽个时间好好写写,嗯,今后要好好写Blog,利用这段时间好好整理一下自己的思路,这样也好。
这题的题意就不说了,汉语,没有什么理解上的问题,这题最大的障碍就是在怎样处理等级问题上。开始的时候,我尝试着用Bellman_ford,在松弛的时候加上等级的处理,但是我理解错了一句话,“地位差距超过一定限制的两个人之间不会进行任何形式的直接接触,包括交易。“这句话是说从源点开始扩展的所有点都必须在源点的等级限制范围内。而Bellman
_ford的松弛处理则并不能保证这一点。所以很不幸的WA了,然后看discuss里的人用Dijkstra做的,又想了一下,Dijkstra是从源点一层一层向前扩展,正好符合这题的特点,想明白了怎么做,但是对于代码实现还是花了一点时间,这个需要锻炼。
代码:
View Code
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream> #include <algorithm> #include <queue> #include <math.h> #define N 104 #define INF 10000000 using namespace std ; struct node { int cost , level ; }p[N] ; int map[N][N] , vist[N] , dis[N] , lev[N] ;//vist[i]标记这个点是否遍历过,dis[i]表示源点到 //点i的最短距离,lev[i]记录点i的等级 int n , w , m ; void init() { int i ; memset( vist , 0 , sizeof ( vist )) ; for ( i = 1 ; i <= n ; i++ ) dis[i] = INF ; dis[1] = 0 ; } int Dijkstra() { int min_lev , max_lev ; int ans = p[1].cost ; int i , j , k , pos ; for ( i = 0 ; i < m ; i++ ) { //计算等级范围 min_lev = lev[i] - w ; max_lev = lev[i] ; if ( p[1].level < min_lev || p[1].level > max_lev ) continue ; init( ); //dijkstra计算出这个等级范围内的最短路。 for ( j = 1 ; j <= n ; j++ ) { pos = -1 ; for ( k = 1 ; k <= n ; k++ ) if ( !vist[k] && ( pos == -1 || dis[k] < dis[pos] ) && ( p[k].level >= min_lev && p[k].level <= max_lev )) pos = k ; vist[pos] = 1 ; for( k = 1 ; k <= n ; k++ ) if ( !vist[k] && dis[k] > dis[pos] + map[pos][k] &&( p[k].level >= min_lev && p[k].level <= max_lev)) dis[k] = dis[pos] + map[pos][k] ; } //加上最后那个物品的价值,找出最小值 for ( j = 1 ; j <= n ; j++ ) if ( dis[j] + p[j].cost < ans ) ans = dis[j] + p[j].cost ; } return ans ; } int main() { int i , j , x , y , t ; while ( scanf ( "%d%d" , &w , &n) != EOF ) { for ( i = 1 ; i <= n ; i++ ) for ( j = 1 ; j <= n ; j++ ) map[i][j] = INF ; m = 0 ; for ( i = 1 ; i <= n ; i++ ) { scanf ( "%d%d%d" , &p[i].cost , &p[i].level , &t ); lev[m++] = p[i].level ; while ( t-- ) { scanf ( "%d%d" , &x , &y ) ; map[i][x] = y ; } } printf ( "%d\n" , Dijkstra()); } return 0 ; }