Dijkstra(DP)
类型题 :[UVA - 10269](https://www.cnblogs.com/AsuraS/articles/11128037.html)状态dp[i][j] 表示的是从起点到当前节点i时,是否用了免去最贵票的机会,j == 0表示已用,j == 1表示还没用。
那么存在3种状态转移
- dp[v][0] = dp[u][1]+G[u][v]-maxn[v]
- dp[v][0] = dp[u][0]+G[u][v]
- dp[v][1] = dp[u][1]+G[u][v];
maxn[i] 表示的是从起点到当前节点i的途中,最贵的票是多少
#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cmath>
#include <stack>
#include <map>
using namespace std;
const int INF = 0x3f3f3f3f;
const int Maxn = 200+10;
struct Node {
int i, j, w;
Node(int x, int y, int z):i(x), j(y), w(z){
}
bool operator < (const Node a1) const {
return w > a1.w;
}
};
int G[Maxn][Maxn], dp[Maxn][2], maxn[Maxn];
bool vis[Maxn][2];
void Dij(int s, int t, int n) {
for(int i = 0; i < n; ++i) {
dp[i][0] = dp[i][1] = INF;
vis[i][0] = vis[i][1] = false;
maxn[i] = 0;
}
dp[s][1] = 0;
vis[s][0] = true;
priority_queue <Node> qu;
qu.push(Node(s, 1, 0));
while(!qu.empty()) {
Node u = qu.top(); qu.pop();
if(vis[u.i][u.j]) continue;
vis[u.i][u.j] = true;
for(int i = 0; i < n; ++i) {
if(G[u.i][i] != INF) {
maxn[i] = max(maxn[u.i], G[u.i][i]);
if(dp[i][0] > dp[u.i][0]+G[u.i][i]) {
dp[i][0] = dp[u.i][0]+G[u.i][i];
qu.push(Node(i, 0, dp[i][0]));
}
if(dp[i][0] > dp[u.i][1]+G[u.i][i]-maxn[i]) {
dp[i][0] = dp[u.i][1]+G[u.i][i]-maxn[i];
qu.push(Node(i, 0, dp[i][0]));
}
if(dp[i][1] > dp[u.i][1]+G[u.i][i]) {
dp[i][1] = dp[u.i][1]+G[u.i][i];
qu.push(Node(i, 1, dp[i][1]));
}
}
}
}
cout << min(dp[t][0], dp[t][1]) << endl;
}
int main(void)
{
string s, t;
while(cin >> s >> t) {
int n, index = 0;
map <string, int> mp;
mp[s] = index++; mp[t] = index++;
cin >> n;
string u, v; int w;
memset(G, INF, sizeof(G));
for(int i = 0; i < n; ++i) {
cin >> u >> v >> w;
if(mp.find(u) == mp.end()) mp[u] = index++;
if(mp.find(v) == mp.end()) mp[v] = index++;
int x = mp[u], y = mp[v];
G[x][y] = min(G[x][y], w);
}
Dij(mp[s], mp[t], index);
}
return 0;
}
浙公网安备 33010602011771号