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 }