这题从下午七点做到晚上的九点半,才做出来。
题意,有一个人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 }
时间: 2024-10-13 00:34:50