【题意】
大意是有一个人从某个城市要到另一个城市(点数<=30)
然后有n个马车票,相邻的两个城市走的话要消耗掉一个马车票。
花费的时间呢,是马车票上有个速率值,用边/速率就是花的时间。
问最后这个人花费的最短时间是多少
【解题方法】比较裸的状压dp了,dp[S][v]代表当前消耗了S集合的车票走到v花费的最小时间,可以用spfa来转移也可以直接转移,因为这个图是一个DAG!
【AC代码】
//POJ.2686
//Traveling by Stagecoach.
//DAG 的直接转移
#include <vector>
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
#define INF 1e9
const int maxn=33;
int n,m,p,a,b;
typedef pair<int,int>P;
vector<P>G[maxn];
int ticket[10];
double dp[1<<10][33];//消耗了s集合的票到达v花费的最小时间
void init()
{
for(int i=0; i<300; i++)
{
fill(dp[i],dp[i]+32,INF);
}
for(int i=0; i<=m; i++) G[i].clear();
}
int main()
{
int u,v,w;
while(scanf("%d%d%d%d%d",&n,&m,&p,&a,&b)!=EOF)
{
if(n==0&&m==0&&p==0&&a==0&&b==0) break;
for(int i=0; i<n; i++) scanf("%d",&ticket[i]);
init();
for(int i=1; i<=p; i++)
{
scanf("%d%d%d",&u,&v,&w);
G[u].push_back(make_pair(v,w));
G[v].push_back(make_pair(u,w));
}
dp[0][a]=0;
double res=INF;
int to,weight;
for(int S=0; S<(1<<n); S++)
{
// res=min(res,dp[S][b]);
for(int v=1; v<=m; v++)
{
for(int i=0; i<n; i++)
{
if(!(S&(1<<i))){
// puts("success");
//使用了车票i,从v点移动到了to点
for(int u=0; u<(int)G[v].size(); u++)
{
to=G[v][u].first;
weight=G[v][u].second;
dp[S|(1<<i)][to] = min(dp[S|(1<<i)][to],dp[S][v]+(double)weight/ticket[i]);
}
}
}
}
res=min(res,dp[S][b]);
}
if(res==INF)
{
printf("Impossible\n");
}
else
{
printf("%.3f\n",res);
}
}
}
//Spfa 转移
#include <queue>
#include <vector>
#include <cstdio>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
#define INF 1e9
const int maxn=33;
int n,m,p,a,b;
int vis[300][33];
typedef pair<int,int>P;
vector<P>G[maxn];
double dp[300][33];
int ticket[33];
void init()
{
for(int i=0; i<300; i++) fill(dp[i],dp[i]+32,INF);
for(int i=0; i<=m; i++) G[i].clear();
memset(vis,false,sizeof(vis));
}
void spfa()
{
queue<P>qu;
memset(vis,false,sizeof(vis));
while(!qu.empty()) qu.pop();
dp[0][a]=0;
vis[0][a]=1;
qu.push(make_pair(0,a));
P now;
while(!qu.empty())
{
now=qu.front();
qu.pop();
int S=now.first;
int v=now.second;
for(int i=0; i<n; i++)
{
if(!(S&(1<<i)))
{
for(int u=0; u<(int)G[v].size(); u++)
{
int to=G[v][u].first;
int weight=G[v][u].second;
if(dp[S|(1<<i)][to]>dp[S][v]+(double)weight/ticket[i])
{
dp[S|(1<<i)][to]=dp[S][v]+(double)weight/ticket[i];
if(!vis[S|(1<<i)][to])
{
vis[S|(1<<i)][to]=1;
qu.push(make_pair(S|(1<<i),to));
}
}
}
}
}
}
double res=INF;
for(int i=0; i<(1<<n); i++) res=min(res,dp[i][b]);
if(res!=INF)
printf("%.3f\n",res);
else
printf("Impossible\n");
}
int main()
{
while(scanf("%d%d%d%d%d",&n,&m,&p,&a,&b)!=EOF)
{
if(n==0&&m==0&&p==0&&a==0&&b==0) break;
int u,v,w;
init();
for(int i=0; i<n; i++) scanf("%d",&ticket[i]);
for(int i=0; i<p; i++)
{
scanf("%d%d%d",&u,&v,&w);
G[u].push_back(make_pair(v,w));
G[v].push_back(make_pair(u,w));
}
spfa();
}
}