POJ 1062 dijkstra + 枚举

这题从下午七点做到晚上的九点半,才做出来。

题意,有一个人A,要去人B那里买东西,人B说了一个价格,然后说如果你能把人C的东西弄来,再加上一部分钱(比直接买人B东西的价格少),也能买到。

于是人A又去了人C那里,人C说了同上的话。依次类推。

但是这个交易圈子里有个规定,就是每个人都有一个等级,如果两个人相差k个等级以上,是不能产生直接或者间接交易的。

问最后你一定要买到人A的东西,最少要多少钱。

 

分析,分析过后,可以通过交易关系,A需要B的东西,将一条边由B连上A,建立有向图。如果没有等级制度,就是一个裸的dijkstra。存在等级制度加大了题目难度。一个比较简单的处理方法是,如果人A的等级为k,最后存在一条最短路。

那么最短路上的人的权值一定在区间 [k-m,k] [k-m+1,k+1] [k-m+2,k+2] ...... [k,k+m] 这些区间中。枚举区间范围,然后每个范围进行dijkstra,纪录最小答案。

注意细节问题就好。

这题数据很小啊,于是就没有套优先队列优化。

 1 /* When all else is lost the future still remains. */
 2 /* You can be the greatest */
 3 #define rep(X,Y,Z) for(int X=(Y);X<(Z);X++)
 4 #define drep(X,Y,Z) for(int X=(Y);X>=(Z);X--)
 5 #define fi first
 6 #define se second
 7 #define mk(X,Y) make_pair((X),(Y))
 8 #define inf 0x3f3f3f3f
 9 #define clr(X,Y) memset(X,Y,sizeof(X))
10 #define pb push_back
11 //head
12 #include <iostream>
13 #include <stdio.h>
14 #include <queue>
15 #include <algorithm>
16 #include <string>
17 #include <map>
18 #include <string.h>
19 using namespace std;
20 #define maxN 110
21 vector<pair<int,int> > cur[maxN];
22 int val[maxN];
23 int lev[maxN];
24 int dis[maxN];
25 bool mark[maxN];
26 void init(int n){
27     rep(i,0,n+1) cur[i].clear();
28     clr(mark,0);
29     return ;
30 }
31 int find(int n){
32     int ans = -1;
33     int min_val = 2 * inf;
34     rep(i,1,n+1){
35         if(mark[i]) continue;
36         if(dis[i] < min_val){
37             min_val = dis[i];
38             ans = i;
39         }
40     }
41     return ans ;
42 }
43 int dij(int n , int m){
44     int ans = val[1];
45     rep(low,lev[1]-m,lev[1]+1){
46         int p;
47         int high = low + m;
48         rep(i,1,n+1) dis[i] = val[i];
49         clr(mark,0);
50         //
51         while((p = find(n)) != -1){
52             if(mark[1]) break;
53             //printf("%d \n",p);
54             //check(n);
55             mark[p] = 1;
56             if(lev[p] > high || lev[p] < low) continue;
57             int size = cur[p].size();
58             rep(i,0,size){
59                 int aim = cur[p][i].fi;
60                 int w = cur[p][i].se;
61                 if(lev[aim] < low || lev[aim] > high) continue;
62                 dis[aim] = min(dis[aim],dis[p] + w);
63             }
64         }
65         ans = min(ans,dis[1]);
66     }
67     return ans;
68 }
69 int main(){
70     int m , n;
71     while(~scanf("%d %d",&m,&n)){
72         init(n);
73         rep(i,1,n+1){
74             int w , l , num;
75             scanf("%d %d %d",&w,&l,&num);
76             val[i] = w; lev[i] = l;
77             rep(j,0,num){
78                 int a , b;
79                 scanf("%d %d",&a,&b);
80                 cur[a].pb(mk(i,b));
81             }
82         }
83         printf("%d\n",dij(n,m));
84     }
85     return 0;
86 
87 }

 

posted @ 2016-10-13 22:20  ACMZZ  阅读(259)  评论(0编辑  收藏  举报