CF#335 Intergalaxy Trips

 Intergalaxy Trips
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

The scientists have recently discovered wormholes — objects in space that allow to travel very long distances between galaxies and star systems.

The scientists know that there are n galaxies within reach. You are in the galaxy number 1 and you need to get to the galaxy number n. To get from galaxy i to galaxy j, you need to fly onto a wormhole (i, j) and in exactly one galaxy day you will find yourself in galaxy j.

Unfortunately, the required wormhole is not always available. Every galaxy day they disappear and appear at random. However, the state of wormholes does not change within one galaxy day. A wormhole from galaxy i to galaxy j exists during each galaxy day taken separately with probability pij. You can always find out what wormholes exist at the given moment. At each moment you can either travel to another galaxy through one of wormholes that exist at this moment or you can simply wait for one galaxy day to see which wormholes will lead from your current position at the next day.

Your task is to find the expected value of time needed to travel from galaxy 1 to galaxy n, if you act in the optimal way. It is guaranteed that this expected value exists.

Input

The first line of the input contains a single integer n (1 ≤ n ≤ 1000) — the number of galaxies within reach.

Then follows a matrix of n rows and n columns. Each element pij represents the probability that there is a wormhole from galaxy i to galaxy j. All the probabilities are given in percents and are integers. It is guaranteed that all the elements on the main diagonal are equal to 100.

Output

Print a single real value — the expected value of the time needed to travel from galaxy 1 to galaxy n if one acts in an optimal way. Your answer will be considered correct if its absolute or relative error does not exceed 10 - 6.

Namely: let's assume that your answer is a, and the answer of the jury is b. The checker program will consider your answer correct, if .

Sample test(s)
input
3
100 50 50
0 100 80
0 0 100
output
1.750000000000000
input
2
100 30
40 100
output
3.333333333333333
Note

In the second sample the wormhole from galaxy 1 to galaxy 2 appears every day with probability equal to 0.3. The expected value of days one needs to wait before this event occurs is .

 

题意:有n个点,每天可以从i到j的概率是P(i, j),每天也可以选择留在原地,问去到n的期望天数。

分析:这题是这样的。

如果我们从终点往前推,会简单很多。因为从前往后的话很难确定有哪些点转移到自身。

从终点开始的话,显然一开是在终点的天数是0。

又发现,每个点显然只能从更优(期望更小)的点转移到自己。

由于是从后往前推,所以这意味这已经推过的点不会再推。

所以,这是一个类似最短路的过程。

推的过程是这样的

设比x点优秀的点是v[1],v[2].....v[c]

那么x的期望显然满足

dp[x] = dp[v[1]] * p(x, v[1]) + dp[v[2]] * p(x, v[2]) * (1 - p(x, v[1]) ) + dp[v[3]] * p(x, v[3]) * (1 - p(x, v[2]) ) * (1 - p(x, v[1]) ) + ..... + dp[v[c]] * p(x, v[c]) * (1 - p(x, v[2]) ) * (1 - p(x, v[1]) ) * ..... * (1 - p(x, v[c - 1])) + dp[x] * (1 - p(x, v[2]) ) * (1 - p(x, v[1]) ) * ..... * (1 - p(x, v[c])) + 1

其中(1 - p(x, v[2]) ) * (1 - p(x, v[1]) ) * ..... * (1 - p(x, v[c]))是它留在原地的概率。

然后变形

dp[x] = (    dp[v[1]] * p(x, v[1]) + dp[v[2]] * p(x, v[2]) * (1 - p(x, v[1]) ) + dp[v[3]] * p(x, v[3]) * (1 - p(x, v[2]) ) * (1 - p(x, v[1]) ) + ..... + dp[v[c]] * p(x, v[c]) * (1 - p(x, v[2]) ) * (1 - p(x, v[1]) ) * ..... * (1 - p(x, v[c - 1]))      + 1    ) / (1 -  (1 - p(x, v[2]) ) * (1 - p(x, v[1]) ) * ..... * (1 - p(x, v[c])) )

这样就可以转移了。。。

 1 /**
 2 Create By yzx - stupidboy
 3 */
 4 #include <cstdio>
 5 #include <cstring>
 6 #include <cstdlib>
 7 #include <cmath>
 8 #include <deque>
 9 #include <vector>
10 #include <queue>
11 #include <iostream>
12 #include <algorithm>
13 #include <map>
14 #include <set>
15 #include <ctime>
16 #include <iomanip>
17 using namespace std;
18 typedef long long LL;
19 typedef double DB;
20 #define MIT (2147483647)
21 #define INF (1000000001)
22 #define MLL (1000000000000000001LL)
23 #define sz(x) ((int) (x).size())
24 #define clr(x, y) memset(x, y, sizeof(x))
25 #define puf push_front
26 #define pub push_back
27 #define pof pop_front
28 #define pob pop_back
29 #define mk make_pair
30 
31 inline int Getint()
32 {
33     int Ret = 0;
34     char Ch = ' ';
35     bool Flag = 0;
36     while(!(Ch >= '0' && Ch <= '9'))
37     {
38         if(Ch == '-') Flag ^= 1;
39         Ch = getchar();
40     }
41     while(Ch >= '0' && Ch <= '9')
42     {
43         Ret = Ret * 10 + Ch - '0';
44         Ch = getchar();
45     }
46     return Flag ? -Ret : Ret;
47 }
48 
49 const DB EPS = 1e-7;
50 const int N = 1010;
51 int n, data[N][N];
52 DB dp[N], stay[N], cnt[N];
53 bool visit[N];
54 
55 inline void Input()
56 {
57     scanf("%d", &n);
58     for(int i = 1; i <= n; i++)
59         for(int j = 1; j <= n; j++)
60             scanf("%d", &data[i][j]);
61 }
62 
63 inline void Solve()
64 {
65     for(int i = 1; i <= n; i++) dp[i] = INF, stay[i] = 1.0, cnt[i] = 0.0;
66     dp[n] = 0;
67     for(int k = 1; k <= n; k++)
68     {
69         int idx = -1;
70         DB mn = INF;
71         for(int i = 1; i <= n; i++)
72             if(!visit[i] && mn >= dp[i])
73                 mn = dp[i], idx = i;
74         
75         if(idx == 1)
76         {
77             printf("%.12lf\n", dp[1]);
78             break;
79         }
80         
81         visit[idx] = 1;
82         for(int i = 1; i <= n; i++)
83             if(!visit[i])
84             {
85                 cnt[i] += stay[i] * dp[idx] * (0.01 * data[i][idx]);
86                 stay[i] *= 1 - 0.01 * data[i][idx];
87                 if(fabs(1 - stay[i]) > EPS)
88                     dp[i] = (1 + cnt[i]) / (1 - stay[i]);
89             }
90     }
91 }
92 
93 int main()
94 {
95     freopen("a.in", "r", stdin);
96     Input();
97     Solve();
98     return 0;
99 }
View Code

 

转载于:https://www.cnblogs.com/StupidBoy/p/5062663.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值