POJ1062 昂贵的聘礼

题目链接:
http://poj.org/problem?id=1062

  虽然说是一道中文题,表示还是看了好久才弄懂题意。将题抽象出来就是一个最短路问题,但是因为有交易的限制,就是交易的所有人员中的最大等级差不超过M。

  其实用测试数据举个例子就比较清楚了:

1 4
10000 3 2
2 8000
3 5000
1000 2 1
4 200
3000 2 1
4 200
50 2 0
开始的等级限制是1(最大等级差),接着是4个物品。最开始的也就是酋长的物品。其实将上面处理为
图就是下面的形式:

 

1号是酋长,先不考虑等级的问题,那么就有很多种付钱的方式。比如说可以一次付完,即10000元,当然也可以是用1000元买一个2号物品,然后再用8000元即可,这样一共就是9000元。是不是从中看出了什么。。。

那就是从1号进行出发,假设最终选择的点是n号,那么就是1号到n号的最短路再加买n号物品的花销就是最少的花费。。。在这个的基础上,再考虑下等级的限制,可以直接枚举一次交易的最小或者最大的等级。。假设枚举的是最小的等级w,那么节点有效的基础是等级在[w, w+M]之间。然后在这些点中求最短路即可了。。

 

把dijkstra写残了, 求最短的距离时,用原始的路径去比较,没有用更新后的距离,一直WA,找了好久才发现。。。

如果一直WA的话,大家可以尝试仔细检查下最短路。。。。。。。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 using namespace std ;
 5 /*
 6 POJ1062:
 7 */
 8 const int INF = 1e7 ;
 9 const int MAXM = 105 ;
10 int M, N ;
11 struct nodes
12 {
13     int val, lever ;
14 };
15 nodes goods[MAXM] ;
16 int map[MAXM][MAXM], lev[MAXM] ;
17 int dis[MAXM], res[MAXM] ;
18 bool vis[MAXM] ;
19 // 
20 void input(){
21     for( int i = 0; i < MAXM; i++ ){
22         for( int j = 0; j < MAXM; j++ )    map[i][j] = INF ;
23         //map[i][i] = 0 ;
24     }
25     scanf("%d%d",&M, &N) ;
26     for( int i = 1; i <= N; i++ ){
27         int num ;
28         scanf("%d%d%d", &goods[i].val, &goods[i].lever, &num) ;
29         lev[i-1] = goods[i].lever ;
30         for( int j = 0; j < num; j++ ){
31             int tmp1, tmp2 ;
32             scanf("%d%d", &tmp1, &tmp2) ;
33             map[i][tmp1] = tmp2 ;
34         }
35     }
36 }
37 //
38 void dijkstra(int u){
39     //cout << "u  " << u << endl ;
40     for( int i = 1; i <= N; i++ ){
41         dis[i] = INF ;
42         vis[i] = false ;
43     }
44     dis[1] = 0 ;
45      for( int i = 1; i <= N; i++ ){
46         int tmp = INF, k = i ;
47         if( goods[i].lever < u || goods[i].lever > u+M )    continue ;
48         //cout << i << endl ;
49         for( int j = 1; j <= N; j++ ){
50             if( vis[j] )    continue ;
51             if( tmp > dis[j] && goods[j].lever >= u && goods[j].lever <= u+M ){ /////tmp > map[i][j]
52                 //cout << "ssss" << endl ;
53                 tmp = dis[j] ;
54                 k = j ;
55             }
56         }
57 //        cout << "k  " << k << endl ;
58         vis[k] = true ;
59         if( dis[k] == INF )    break ;
60         for( int t = 1; t <= N; t++ ){
61             if( goods[t].lever >= u && goods[t].lever <= u+M && !vis[t] )
62                 dis[t] = min(dis[t], dis[k]+map[k][t]) ;
63         }
64     }
65     for( int i = 1; i <= N; i++ ){
66         res[i] = min(res[i], dis[i]) ;
67     }
68 }
69 //
70 void solve(){
71     sort(lev, lev+N) ;
72     for( int i = 1; i <= N; i++ )    res[i] = INF ;
73     int u = -1 ;
74     for( int i = 0; i < N; i++ ){
75         if( lev[i] == u )    continue ;
76         u = lev[i] ;
77         if( goods[1].lever <= u+M && goods[1].lever >= u ){
78             dijkstra(u) ;
79         }
80     }
81     int asw = INF ;
82     for( int i = 1; i <= N; i++ ){
83         asw = min(asw, res[i]+goods[i].val) ;
84     }
85     cout << asw << endl ;
86 }
87 //
88 int main(){
89     //freopen("1234.txt", "r", stdin) ;
90     input() ;
91     solve() ;
92     return 0 ;
93 }

 

posted @ 2015-08-01 20:09  ct_usl  阅读(270)  评论(0编辑  收藏  举报