题意:有m个城市,其中有些城市之间 有道路连通,且有一定的距离w,现在你有n张卡,每张卡有个权值t能让经过
通过 道路的费用变为w/t,求从城市a到城市b的 最小的花费。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <algorithm>
#include <set>
using namespace std;
#define MM(a) memset(a,0,sizeof(a))
typedef long long ll;
typedef unsigned long long ULL;
const int mod = 1000000007;
const double eps = 1e-10;
const int inf = 0x3f3f3f3f;
const int big=50000;
int max(int a,int b) {return a>b?a:b;};
double min_(double a,double b) {return a<b?a:b;};
int n,m,p,a,b,t[10];
struct e{
int to;double cost;
};
vector<e> G[35];
double dp[1<<10][35];
void solve()
{
double ans=inf;
for(int s=0;s<=(1<<n)-1;s++)
fill(dp[s]+1,dp[s]+m+1,inf);//不能用memset初始化,因为其只能对整型
dp[(1<<n)-1][a]=0;
for(int s=(1<<n)-1;s>=0;s--)
{
ans=min_(ans,dp[s][b]);
for(int u=1;u<=m;u++)//枚举起点u
for(int j=1;j<=n;j++)//使用第j张票
if(s&(1<<(j-1)))
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i].to;
double c=G[u][i].cost;
dp[s&(~(1<<(j-1)))][v]=min_(dp[s&(~(1<<(j-1)))][v],dp[s][u]+c/t[j]);//状态转移方程
}
}
if(ans>=inf-1)
printf("Impossible\n");
else
printf("%.3f\n",ans);
}
int main()
{
while(~scanf("%d %d %d %d %d",&n,&m,&p,&a,&b))
{
if(!n&&!m&&!p&&!a&&!b) break;
for(int i=1;i<=n;i++)
scanf("%d",&t[i]);
for(int i=1;i<=m;i++)
G[i].clear();
int f,t;double c;
for(int i=1;i<=p;i++)
{
scanf("%d %d %lf",&f,&t,&c);
G[f].push_back((e){t,c});
G[t].push_back((e){f,c});
}
solve();
}
return 0;
}
分析:状态压缩dp[s][u]表示在当前剩余票的情况为s(状压),所处城市为u的情况下所需要的最小的花费
不过还需要注意 本解法的枚举顺序,是先枚举当前票的状态...然后再是起点,使用的票,终点。