HDU 4418 Time travel

Time travel

http://acm.hdu.edu.cn/showproblem.php?pid=4418

 

分析:

  因为走到最后在折返,可以将区间复制一份,就变成了只往右走,012343210。

  写出转移方程:

$f[t] = 0$

$f[i] = p_1 \times (f[i +1] + 1) + p_2 \times (f[i +2] + 2) + \cdots$

$ =\sum\limits_{j=1}^{m}p_j \times (f[i + j] + j) $

$= \sum\limits_{j=1}^{m}p_j \times f[i + j] + \sum\limits_{j=1}^{m}p_j\times j$

然后列出线性方程组,用高斯消元求解。

$f[i] = \sum\limits_{j=1}^{m}p_j \times f[i + j] + \sum\limits_{j=1}^{m}p_j\times j$

$\sum\limits_{j=1}^{m}p_j\times j = f[i] - \sum\limits_{j=1}^{m}p_j \times f[i + j]$

补上其他项就是:

$sum =0 \times f[0] +0 \times f[1] + \cdots + f[i] + p_1 \times f[i+1] + p_2 \times f[i+2] + \cdots +0 \times f[n-1] + 0 \times f[n]$

首先bfs判一下能不能到达这个点。

代码:

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<iostream>
 6 #include<cctype>
 7 #include<set>
 8 #include<vector>
 9 #include<queue>
10 #include<map>
11 using namespace std;
12 typedef long long LL;
13 
14 inline int read() {
15     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
16     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
17 }
18 const int N = 505;
19 const double eps = 1e-9;
20 double A[N][N], p[N], sum;
21 bool vis[N];
22 int n, m, s, t;
23 int q[N];
24 
25 bool bfs() {
26     memset(vis, false, sizeof(vis));
27     int L = 1, R = 0;
28     vis[s] = 1;
29     q[++R] = s;
30     while (L <= R) {
31         int u = q[L ++];
32         for (int i=1; i<=m; ++i) {
33             int v = (u + i) % n;
34             if (!vis[v] && fabs(p[i]) > eps) vis[v] = 1, q[++R] = v;
35         }
36     }
37     return vis[t] || vis[n - t]; // n-t折叠后的另一侧的点 
38 }
39 void build() {
40     memset(A, 0, sizeof(A));
41     for (int i=0; i<n; ++i) {
42         A[i][i] += 1;
43         if (!vis[i]) { A[i][n] = 1e9; continue;}
44         if (i == t || i == n - t) { A[i][n] = 0; continue; }
45         A[i][n] = sum;
46         for (int j=1; j<=m; ++j) 
47             A[i][(i + j) % n] -= p[j];
48     }
49 }
50 void Gauss() {
51     for (int k=0; k<n; ++k) {
52         int r = k;
53         for (int i=k+1; i<n; ++i) 
54             if (fabs(A[i][k]) > fabs(A[r][k])) r = i;
55         if (k != r) for (int j=k; j<n; ++j) swap(A[k][j], A[r][j]);
56         for (int i=k+1; i<n; ++i) {
57             if (fabs(A[i][k]) > eps) {
58                 double t = A[i][k] / A[k][k];
59                 for (int j=k+1; j<=n; ++j) A[i][j] -= t * A[k][j]; //小于等于n 
60             }
61         }    
62     }
63     for (int i=n-1; i>=0; --i) {
64         for (int j=i+1; j<=n; ++j) 
65             A[i][n] -= A[j][n] * A[i][j];
66         A[i][n] /= A[i][i];
67     }
68     printf("%.2lf\n",A[s][n]);
69 }
70 int main() {
71     int T, d; 
72     scanf("%d",&T);
73     while (T--) {
74         scanf("%d%d%d%d%d",&n, &m, &t, &s, &d);
75         n = (n - 1) << 1;
76         sum = 0;
77         for (int i=1; i<=m; ++i) {
78             scanf("%lf",&p[i]);
79             p[i] = p[i] / 100.0;
80             sum += p[i] * i;
81         }
82         if (s == t) { puts("0.00");continue; }
83         if (d) s = (n - s) % n;
84         if (!bfs()) { puts("Impossible !"); continue;}
85         build();
86         Gauss();
87     }
88     return 0;
89 }

 

posted @ 2018-09-13 16:50  MJT12044  阅读(168)  评论(0编辑  收藏  举报