题目类型 Dijkstra算法的运用
题目意思
中文题目描述
解题方法
先枚举地位的范围(因为第1件物品必须在交易中出现所以范围区间的左端点就是 L1-m -> L1 右端点范围是 L1 -> L1+m)
确定范围后就是类似Dijkstra算法的贪心过程
d[i] 表示交易终点停在第 i 个物品时总共所需的花费 那么每次取最小的 d[i] 去更新其他的 d[] 即可
参考代码 - 有疑问的地方在下方留言 看到会尽快回复的
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
const int INF = 1<<29;
const int maxn = 100 + 10;
struct Node {
int p, l, x;
}node[maxn];
struct PNode {
int d, u;
PNode(int d, int u) : d(d), u(u) {}
PNode(){}
bool operator < (const PNode & rhs) const {
return d > rhs.d;
}
};
vector<int>E[maxn], W[maxn]; // E保存连接的物品 W保存优惠后的花费
int n, m, d[maxn];
bool vis[maxn];
int res;
int Dijkstra(int L, int R) {
for( int i=1; i<=n; i++ ) d[i] = INF;
d[1] = node[1].p;
priority_queue<PNode>q; // 优先队列优化
q.push(PNode(node[1].p, 1));
while(!q.empty()) {
PNode f = q.top(); q.pop();
//printf("ff = %d\n", f.u);
for( int i=0; i<E[f.u].size(); i++ ) {
int v = E[f.u][i];
if(node[v].l >= L && node[v].l <= R) {
if(d[v] > d[f.u] + node[v].p - (node[f.u].p-W[f.u][i])) {
d[v] = d[f.u] + node[v].p - (node[f.u].p-W[f.u][i]);
res = min(d[v], res); // res为最终结果
PNode tmp;
tmp.d = d[v];
tmp.u = v;
q.push(tmp);
}
}
}
}
return res;
}
int main() {
freopen("in", "r", stdin);
while(scanf("%d%d", &m, &n) != EOF) {
for( int i=1; i<=n; i++ ) E[i].clear(), W[i].clear();
for( int i=1; i<=n; i++ ) {
scanf("%d%d%d", &node[i].p, &node[i].l, &node[i].x);
for( int j=0; j<node[i].x; j++ ) {
int a, b;
scanf("%d%d", &a, &b);
E[i].push_back(a);
W[i].push_back(b);
}
}
res = node[1].p;
for( int i=node[1].l-m; i<=node[1].l; i++ ) { // 枚举交易中出现的地位的区间
Dijkstra(i, i+m);
}
printf("%d\n", res);
}
return 0;
}