题意:
给了一个图以及不超过18个自行车点,每个自行车点有w概率没有车,给了骑自行车的速度以及步行的速度,问到达终点的最小期望时间
考点:状压dp,最短路
思路:
首先考虑到达终点的期望时间是如何计算的,很显然我要么直接步行去终点,要么走到某一个自行车点然后有概率拿到自行车去终点或者我拿不到自行车,拿不到自行车有两种选择,直接步行去终点或者继续找到另外的自行车重复此次操作,那么一定有一个最终到达的自行车点,我不管拿没拿到自行车都直接去终点。
可以把所有自行车点想象成二进制串,最终结果一定是我按到达顺序选择某一些自行车点到终点的期望,考虑dp,f[s][j]枚举每一种自行车点的选择情况s与最后到达的自行车点 j,表示我按任意顺序经过这些自行车点且最后一个到达的自行车点为 j 的到终点的最小期望,枚举上一个到达的自行车点在哪转移即可,注意每次算距离要用最短距离跑18遍最短路即可
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll mod=998244353;
const int N=1e5+5;
double f[19][1<<18];
int hard[N];
double lin[19][N];
bool ss[19][N]={0};
ll bj[20],bj1[N];
ll n1;
ll d[100];
double w1[20];
struct duqi{
int i,end;
double k;
};
duqi q[N*2];
struct du{
double jl;
ll i;
operator<(du w1)const{
return jl>w1.jl;
}
};
du t1,t2;
priority_queue<du>w;
void zdl(ll n){
ll i,j,l;
for(i=0;i<=n1;i++)
for(j=1;j<=n;j++)lin[i][j]=1e12;
for(i=0;i<=n1;i++){
t1.i=bj[i];t1.jl=0;lin[i][t1.i]=0;
w.push(t1);
while(!w.empty()){
t2=w.top();w.pop();
if(ss[i][t2.i]==1)continue;
ss[i][t2.i]=1;
for(j=hard[t2.i];j!=0;j=q[j].end){
l=q[j].i;
if(lin[i][l]>q[j].k+lin[i][t2.i]){
lin[i][l]=q[j].k+lin[i][t2.i];
t1.i=l;t1.jl=lin[i][l];
w.push(t1);
}
}
}
}
}
double gl[1<<18];
int main()
{
ll i,j,k,l,n,m,sum,t,l1,r,r1,mid,pa,pb,g,max1,p,i1,w2;
double v1,v2,jl,x,h,min1;
p=0;
scanf("%lf%lf",&v1,&v2);
scanf("%lld%lld",&n,&m);
for(i=1;i<=m;i++){
scanf("%lld%lld%lf",&l,&r,&jl);
q[++p].i=r;q[p].end=hard[l];q[p].k=jl;hard[l]=p;
q[++p].i=l;q[p].end=hard[r];q[p].k=jl;hard[r]=p;
}
scanf("%lld",&n1);
bj[0]=1;
for(i=1;i<=n1;i++){
scanf("%lld%lf",&k,&x);
bj[i]=k;bj1[k]=i;w1[i]=x;
}
zdl(n);
if(lin[0][n]>=1e10){
printf("-1");return 0;
}
d[0]=1;
for(i=1;i<=20;i++)d[i]=d[i-1]*2;
for(i=0;i<=d[n1]-1;i++){
h=1;
for(j=0;j<n1;j++)if((1<<j)&i)h=h*(w1[j+1])/100;
gl[i]=h;
}
min1=1e12;
for(j=1;j<=n1;j++){
f[j][d[j-1]]=lin[0][bj[j]]/v1+lin[j][n]*(1-w1[j]/100)/v2;
min1=min(min1,f[j][d[j-1]]+gl[d[j-1]]*lin[j][n]/v1);
}
g=0;
for(i=1;i<=d[n1]-1;i++){
if(i==d[g]){
g++;continue;
}
for(j=1;j<=n1;j++){
f[j][i]=1e12;
if((1<<(j-1))&i){
for(l=1;l<=n1;l++){
if((1<<l-1)&i&&l!=j){
f[j][i]=min(f[j][i],f[l][i-d[j-1]]+lin[l][bj[j]]*gl[i-d[j-1]]/v1+gl[i-d[j-1]]*lin[j][n]*(1-w1[j]/100)/v2);
}
}
}
min1=min(min1,f[j][i]+gl[i]*lin[j][n]/v1);
}
}
printf("%.6lf",min(min1,lin[0][n]/v1));
}