概率dp light 1321

题意:给定一张无向图,每条边都有一个通过的概率 ,如果无法通过,那么就要回到起点重新出发
从起点到终点的时间固定为K,如果成功到达,又需要额外花费K的时间,问走S次的最小期望时间

思路:这道题分为两部分,第一部分是求spfa,第二部分是通过得出的最大的概率的那条路算出答案;怎么算呢,通过最短路求出后,设期望值为E,成功概率为p,如果成功,期望值为p*2k,如果不成功,期望值为(1-p)*(E+2k)因此E=p*2k+(1-p)*(E+2k),化简为E=2k/p最后再乘上s

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<math.h>
 4 #include<string.h>
 5 #include<queue>
 6 using namespace std;
 7 const int maxn=1e4+10;
 8 const int inf=0x3f3f3f3f;
 9 int head[maxn],num=-1;
10 int s,t;
11 double dis[maxn];int vis[maxn];
12 struct node
13 {
14     int v,next;
15     double w;
16 }G[maxn];
17 void build(int u,int v,double w)
18 {
19     G[++num].v=v;G[num].w=w;G[num].next=head[u];head[u]=num;
20     G[++num].v=u;G[num].w=w;G[num].next=head[v];head[v]=num;
21 }
22 void init()
23 {
24     memset(head,-1,sizeof(head));
25     num=-1;
26 }
27 void SPFA()
28 {
29     memset(dis,0,sizeof(dis));
30     dis[0]=1;
31     queue<int>q;
32     q.push(0);
33     vis[0]=1;
34     while(!q.empty()){
35       //  printf("11111111111111111111111111\n");
36         int u=q.front();
37         q.pop();
38         vis[u]=0;
39         for(int i=head[u];i!=-1;i=G[i].next){
40             int v=G[i].v;double w=G[i].w;
41             if(dis[v]<dis[u]*w){
42                 dis[v]=dis[u]*w;
43                 if(!vis[v]){
44                     q.push(v);
45                     vis[v]=1;
46                 }
47             }
48         }
49     }
50 }
51 int main()
52 {
53     int T;
54     scanf("%d",&T);
55     int cnt=0;
56     while(T--){
57         init();
58         int n,m,s,k;
59         scanf("%d%d%d%d",&n,&m,&s,&k);
60         for(int i=1;i<=m;i++){
61             int u,v;double w;
62             scanf("%d%d%lf",&u,&v,&w);
63             w=w/100;
64             build(u,v,w);
65         }
66         SPFA();
67         double ans=dis[n-1];
68         double tmp=1.0/ans;
69         tmp=(double)(tmp*2*k*s);
70         printf("Case %d: %lf\n",++cnt,tmp);
71     }
72     return 0;
73 }

 

 

posted @ 2019-09-29 19:57  古比  阅读(162)  评论(0编辑  收藏  举报