题解:SP1700 TRSTAGE - Traveling by Stagecoach
__Deng_Rui_Song__ · · 题解
可怕的状压dp
咳咳,言归正传
problem
传送门
题意已经很清楚了,我就不再叙述一遍了
solution
Q1:为啥是状压 dp?
A1:看看数据范围:票和城市很小,并且都只有两种状态,符合状压 dp 性质,接下来 dp 四步走。
Q2:dp 状态是什么?
A2:状压城市有点不现实,但是可以状压票,不难想到设
Q3:答案是什么?
A3:由于最后票的状态不确定,所以当然是
Q4:dp 转移怎么写?
A4:枚举上一个城市 超巨的你:废话),票 超巨的你:又一句废话),城市
Q5:初始化?
A5:很明显,
Q6:怎么实现?
A6:可以用邻接矩阵,邻接表,链式前向星存图,我用的是邻接表存图。
code
#include<bits/stdc++.h>
using namespace std;
struct node{int v,w;};
int n,m,p,a,b,t[8];
double dp[256][35];
vector<node> g[35];
void solve(){
for (int i = 0; i < n; i++) cin >> t[i];
while (p--){
int x,y,w;
cin >> x >> y >> w;
g[x].push_back({y,w});
g[y].push_back({x,w});
}
for (int i = 0; i < 1 << n; i++) for (int j = 1; j <= m; j++) dp[i][j] = 1e9;
dp[0][a] = 0;//初始化
for (int i = 1; i < 1 << n; i++)//票的状态
for (int j = 1; j <= m; j++)//当前城市
for (int k = 0; k < g[j].size(); k++)//上一个城市
for (int x = 0; x < n; x++)//上一个用的票
if (i >> x & 1)//如果用了这个票
dp[i][j] = min(dp[i][j],dp[i ^ 1 << x][g[j][k].v] + g[j][k].w * 1.0 / t[x]);//转移
double ans = 1e9;
for (int i = 0; i < (1 << n); i++) ans = min(ans,dp[i][b]);//答案
(ans == 1e9 ? cout << "Impossible\n" : cout << fixed << setprecision(3) << ans << '\n');
for (int i = 1; i <= m; i++) g[i].clear();//多测不清空,爆零两行泪
}
int main(){
while (cin >> n >> m >> p >> a >> b){
if (!n) return 0;
solve();
}
return 0;
}