题意:中文题……
解法:dijkstra。建图建不明白了……绕了好久……最终目标是买1号物品,那么以1为起点,求到所有点的最短路,边权为优惠价格,一条路的最小值为这条路所有边权之和加终点的价格。对于等级的限制条件,每次枚举一个等级区间,只计算区间内点的最短路。
代码:dijkstra又是我自己照流程写的……目测很屎= =但是又懒得找模板……
#include<stdio.h> #include<iostream> #include<algorithm> #include<string> #include<string.h> #include<math.h> #include<limits.h> #include<time.h> #include<stdlib.h> #include<map> #include<queue> #include<set> #include<stack> #include<vector> #define LL long long using namespace std; struct node { int v, val; node(int v, int val) : v(v), val(val) {} node() {} }; vector <node> v[105]; int price[105]; int level[105]; int dis[105]; bool vis[105]; int n, m; const int inf = 100000000; void dij(int l) { for(int i = 0; i < 105; i++) { dis[i] = inf; vis[i] = 0; } if(level[1] < l || level[1] > l + m) return; dis[1] = 0; vis[1] = 1; int len = v[1].size(); for(int i = 0; i < len; i++) { int u = v[1][i].v; if(level[u] < l || level[u] > l + m) continue; dis[u] = v[1][i].val; } while(1) { int u = -1, minn = inf; for(int i = 1; i <= n; i++) { if(!vis[i] && (level[i] >= l && level[i] <= l + m)) { if(dis[i] < minn) { minn = dis[i]; u = i; } } } if(u == -1) break; vis[u] = 1; for(int i = 0; i < v[u].size(); i++) { int tmp = v[u][i].v; if(level[tmp] >= l && level[tmp] <= l + m) { dis[tmp] = min(dis[tmp], v[u][i].val + dis[u]); } } } } int main() { while(~scanf("%d%d", &m, &n)) { for(int i = 0; i < 105; i++) v[i].clear(); int minn = inf, maxn = 0; for(int i = 1; i <= n; i++) { int num; scanf("%d%d%d", &price[i], &level[i], &num); minn = min(level[i], minn); maxn = max(level[i], maxn); for(int j = 0; j < num; j++) { int a, b; scanf("%d%d", &a, &b); v[i].push_back(node(a, b)); } } int ans = inf; minn = max(minn, level[1] - m); for(int i = minn; i <= maxn; i++) { dij(i); for(int j = 1; j <= n; j++) ans = min(ans, dis[j] + price[j]); } printf("%d ", ans); } return 0; }