题面太长了就不放了。
题目给你 n,m,p,a,b 5个数,分别代表票数,点数,边数,起点和终点,每张票有一个权值,每条边有一个权值,每走一条边消耗一张票,代价为边权值/票权值,问是否能从起点走到终点,以及最小的总代价是多少。
刚开始写的时候莫名其妙给自己证明了一下最短路即为最优路,然后把路经边的权值排序后再和票权值匹配,于是就开心地过不了样例,即5/3 + 2/1 < 3/3 + 1/3。dp真的是一生之敌。
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<iomanip>
#include<cstring>
#include<cmath>
#include<ctime>
#define outtime() cerr<<"User Time = "<<(double)clock()/CLOCKS_PER_SEC<<endl
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define bug printf("bug**")
#define coutlf(x) cout << fixed << setprecision(x)
#define uncoutlf cout.unsetf(ios::fixed)
#define S_IT set<Node>::iterator
#define endl "\n"
#define fi first
#define se second
#define mp(a,b) make_pair(a,b)
using namespace std;
int gcd(int a,int b) { return b?gcd(b,a%b):a;}
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> pII;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-7;
int com(double a, double b){
if(a - b > eps) return 1;
if(b - a > eps) return -1;
return 0;
}
int n ,m, p, a, b, u, v, w;
int dis[40][40];
double dp[512][40];
//前一位表示状态,后一位表示到某个点,存a在某个状态下到某个点的最短距离
double t[10];
int cmp(double a, double b){
return a - b > eps;
}
void init(){
memset(dp, 127, sizeof(dp));//搞了半天发现double数组memset 0x3f会取一个很小的值
memset(dis, -1, sizeof(dis));
}
void solve(){
while(~scanf("%d %d %d %d %d", &n, &m, &p, &a, &b)){
if(!(a | b | n | m | p)) break;
init();//初始化边和dp距离
for(int i = 0; i < n; ++i) scanf("%lf", &t[i]);
for(int i = 1; i <= p; ++i){
scanf("%d %d %d", &u, &v, &w);
dis[u][v] = dis[v][u] = w;
}
dp[0][a] = 0;
for(int s = 0; s < 1 << n; ++s){//状态表示不会超过2^n
for(int i = 0; i < n; ++i){
if(s >> i & 1){//当前状态下要用第i张票
for(int u = 1; u <= m; ++u){
for(int v = 1; v <= m; ++v){
if(u != v && dis[u][v] >= 0){//两点之间有边
dp[s][v] = min(dp[s][v], dp[s & ~(1 << i)][u] + dis[u][v] / t[i]);
//s&~(1<<i)为不用当前这张票的情况
}
}
}
}
}
}
double ans = inf;
for(int i = 0; i < 1 << n; ++i){
ans = min(ans, dp[i][b]);
}
if(ans == inf) puts("Impossible");
else printf("%.3f\n", ans);
}
}
int main(){
solve();
return 0;
}