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 }