题目描述:
有限车票去走城市,限定起点a,终点b,求最短时间。
题解:
每张车票都不一样,因此到达某个点的描述并不够,而是要再加上已经用了什么票.因此状压dp
重点:
状压dp,dp的状态决定顺序:从0开始
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <ctype.h>
#include <limits.h>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <stack>
#include <set>
#include <bitset>
#define CLR(a) memset(a, 0, sizeof(a))
#define REP(i, a, b) for(int i = a;i < b;i++)
#define REP_D(i, a, b) for(int i = a;i <= b;i++)
typedef long long ll;
using namespace std;
const int maxn = (1<<8) + 100;
const int key = (1<<8) - 1;
const int INF = INT_MAX/2 - 1;
double dp[maxn][100];
int d[maxn][maxn], t[maxn], a, b, p, n, m;
void get_dp()
{
REP_D(i, 0, key)
{
REP_D(j, 0, m)
{
dp[i][j] = INF;
}
}
dp[0][a] = 0;//什么票都没用,在a点
REP_D(i, 0, key)//决定顺序
{
REP_D(j, 0, m - 1)
{
if(!(fabs(dp[i][j] - INF) < 0.0001) )//其实有很多不合法的东西
{
REP_D(k, 0, n - 1)
{
if(((1<<k)&i) == 0)//看用哪一张车票
{
REP_D(z, 0, m - 1)//尝试去另一个地方.
{
if(d[j][z] != INF)
{
dp[(1<<k)|i][z] = min(dp[(1<<k)|i][z], dp[i][j] + d[j][z]*1.0/(1.0*t[k]));
}
}
}
}
}
}
}
}
void solve()
{
get_dp();
double ans = INF;
REP_D(i, 0, key)
{
ans = min(ans, dp[i][b]);
}
if(fabs(ans - INF) < 0.00001)
printf("Impossible\n");
else
printf("%f\n", ans);
}
int main()
{
//freopen("1Ain.txt", "r", stdin);
//freopen("1Aout.txt", "w", stdout);
while(scanf("%d%d%d%d%d", &n, &m, &p, &a, &b))
{
if(!n && !m && !p && !a && !b)
break;
a--;
b--;
REP(i, 0, n)
scanf("%d", &t[i]);
REP_D(i, 0, m - 1)
{
REP_D(j, 0, m - 1)
{
d[i][j] = INF;
}
}
REP(i, 0, p)
{
int x, y, dist;
scanf("%d%d%d", &x, &y, &dist);
x--;
y--;
d[x][y] = dist;
d[y][x] = dist;
}
solve();
}
return 0;
}