http://poj.org/problem?id=1062
题意:有100个物品,每个物品有一个价格值,一个地位值,和他可以用别的物品来补差价换。求换到1号物品的最小代价。
意思就是给一个图,支付起点的点权,然后走边权走到1号点,求最小的代价,其中路上经过的地位值的差不能超过题目的限制。
最暴力的做法,枚举地位的差,每次在反图上跑一次Dijkstra就好。这样貌似进行了多余的拷贝。
#include<algorithm> #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<map> #include<set> #include<stack> #include<string> #include<queue> #include<vector> using namespace std; typedef long long ll; vector<pair<int, int> >G0[105]; vector<pair<int, int> >G[105]; struct Item { int id; int st; int val; } item[105]; int dis[105]; bool vis[105]; priority_queue<pair<int, int> > pq; void dijkstra(int s, int n) { while(!pq.empty()) pq.pop(); for(int i = 1; i <= n; ++i) { dis[i] = 0x3f3f3f3f; vis[i] = 0; } dis[s] = 0; pq.push({-dis[s], s}); while(!pq.empty()) { int u = pq.top().second; pq.pop(); if(vis[u]) continue; vis[u] = 1; for(int i = 0; i < G[u].size(); ++i) { int v = G[u][i].first, w = G[u][i].second; if(dis[v] > dis[u] + w) { dis[v] = dis[u] + w; pq.push({-dis[v], v}); } } } } int main() { #ifdef Yinku freopen("Yinku.in", "r", stdin); #endif // Yinku int m, n; scanf("%d%d", &m, &n); for(int i = 1; i <= n; ++i) { item[i].id = i; scanf("%d%d", &item[i].val, &item[i].st); int x; scanf("%d", &x); while(x--) { int v, w; scanf("%d%d", &v, &w); G0[i].push_back({v, w}); } } int minval = 0x3f3f3f3f; for(int cst = item[1].st - m; cst <= item[1].st; ++cst) { for(int i = 1; i <= n; ++i) G[i].clear(); int dst = cst + m; for(int i = 1; i <= n; ++i) { if(item[i].st >= cst && item[i].st <= dst) { G[i] = G0[i]; } } dijkstra(1, n); for(int i = 1; i <= n; ++i) { dis[i] += item[i].val; if(item[i].st >= cst && item[i].st <= dst) minval = min(minval, dis[i]); } } printf("%d\n", minval); }