题目:http://ac.jobdu.com/problem.php?pid=1086
先构造有向图,再用Dijk算法。实现时注意 set 中点的距离的更新。
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <set>
using namespace std;
typedef long long LL;
const int M = 205;
const LL INF = 1E10;
LL a[M];
LL cost[M][M];
LL dist[M];
bool v[M];
int main()
{
//freopen("data.txt", "r", stdin);
LL L1, L2, L3, C1, C2, C3, A, B, N;
while (scanf("%lld %lld %lld %lld %lld %lld %lld %lld %lld", &L1, &L2, &L3, &C1, &C2, &C3, &A, &B, &N) != EOF) {
memset(v, 0, sizeof(v));
memset(a, 0, sizeof(a));
for (int i = 0; i < M; i++) {
for (int j = 0; j < M; j++) {
cost[i][j] = INF;
}
dist[i] = INF;
}
a[1] = 0;
for (int i = 2; i <= N; i++) {
scanf("%lld", &a[i]);
}
if (A > B) {
int temp = A;
A = B;
B = temp;
}
if (A == B) {
printf("0\n");
continue;
}
for (int i = A; i <= B; i++) {
cost[i][i] = 0;
for (int j = i+1; j <= B; j++) {
LL s = a[j] - a[i];
if ( s > 0 && s <= L1 ) {
cost[i][j] = C1;
} else if (s > L1 && s <= L2) {
cost[i][j] = C2;
} else if (s > L2 && s <= L3) {
cost[i][j] = C3;
} else {
break;
}
}
}
// Dijk算法
set < pair<LL, int> > sdist;
for (int i = A+1; i <= B; i++) {
if (cost[A][i] != INF) {
dist[i] = cost[A][i];
sdist.insert( make_pair(dist[i], i) );
v[i] = true;
}
}
while (!sdist.empty()) {
int next = ( sdist.begin() )->second;
LL mincost = ( sdist.begin() )->first;
sdist.erase(sdist.begin());
dist[next] = mincost; // 确定一点最短路径
if (next == B) {
printf("%lld\n", dist[B]);
break;
} else { // 更新与next相邻的点的距离
for (int i = next+1; i <= B; i++) { // next != B
if (dist[i] > dist[next] + cost[next][i]) {
if (!v[i]) {
dist[i] = dist[next] + cost[next][i];
sdist.insert( make_pair(dist[i], i) );
v[i] = true;
} else {
set < pair<LL, int> >::iterator it;
it = sdist.find( make_pair(dist[i], i) );
if (it != sdist.end()) {
sdist.erase(it);
dist[i] = dist[next] + cost[next][i];
sdist.insert( make_pair(dist[i], i) );
}
}
}
}
}
}
}
return 0;
}