Paid Roads
题意: 1 1 1到 n n n的最小花费, a a a到 b b b的花费为,如果经过 c c c为 p p p,否则为 r r r。
题解: d p [ i ] [ j ] dp[i][j] dp[i][j]表示以 j j j结尾状态为 i i i时的最小花费,则有 d p [ i ∣ 1 < < a ] [ b ] = m i n ( d p [ i ∣ 1 < < a ] [ b ] , d p [ i ] [ a ] + C [ i > > c & 1 ] ) dp[i | 1 << a][b] = min(dp[i | 1 << a][b], dp[i][a] + C[~ i >> c \& 1]) dp[i∣1<<a][b]=min(dp[i∣1<<a][b],dp[i][a]+C[ i>>c&1])
然后因为起点和终点是固定的,所以需要优先考虑接近起点的点。
代码
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int dp[1<<12][12];
struct node {
int a,b,c;
int cost[2];
node() {}
node(int x,int y,int z,int m,int n) {
a = x, b = y, c = z, cost[0] = m, cost[1] = n;
}
bool operator < (const node & u) const {
if(a == u.a) return b < u.b;
return a < u.a;
}
}e[12];
int main()
{
#ifndef ONLINE_JUDGE
freopen("input.in","r",stdin);
#endif
int n,m,a,b,c,p,r;
cin >> n >> m;
for(int i = 0; i < m; ++i) {
cin >> a >> b >> c >> p >> r;
e[i] = node(a - 1,b - 1,c - 1,p,r);
}
sort(e, e+m);
memset(dp, 0x3f, sizeof dp);
dp[0][0] = 0;
for(int i = 0; i < (1 << n) - 1; ++i) {
for(int j = 0; j < m; ++j) {
int a = e[j].a, b = e[j].b, c = e[j].c;
dp[i | 1 << a][b] = min(dp[i | 1 << a][b], dp[i][a] + e[j].cost[~ i >> c & 1]);
}
}
int ans = 1e9;
for(int i = 0; i < (1 << n) - 1; ++i) {
ans = min(ans, dp[i][n -1]);
}
if(ans == 1e9) return puts("impossible"),0;
cout << ans << endl;
return 0;
}