hdu 4481 Time travel(高斯求期望)(转)

(转)http://blog.csdn.net/u013081425/article/details/39240021

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

 

读了一遍题后大体明白意思,但有些细节不太确定。就是当它处在i点处,它有1~m步可以走,但他走的方向不确定呢。后来想想这个方向是确定的,就是他走到i点的方向,它会继续朝着这个方向走,直到转向回头。

首先要解决的一个问题是处在i点处,它下一步该到哪个点。为了解决方向不确定的问题,将n个点转化为2*(n-1)个点。例如当n=4时由原来的0123变为012321,它对应的编号为012345,这样就不用管它哪个方向,统一处理了,当向前走k步时即(i+k)%n。

 

然后设出dp[i]表示在i点处时到达终点的期望步数,那么可列出转移方程dp[i] = ∑( pk * (dp[ (x+k)%n ] +k) )。但是有些点是永远无法到达的,因此先bfs出所有到达的点,然后列出方程组解方程。

有许多注意的点,判断p[i]是否为0等。

  1 #include <stdio.h>
  2 #include <iostream>
  3 #include <map>
  4 #include <set>
  5 #include <list>
  6 #include <stack>
  7 #include <vector>
  8 #include <math.h>
  9 #include <string.h>
 10 #include <queue>
 11 #include <string>
 12 #include <stdlib.h>
 13 #include <algorithm>
 14 //#define LL __int64
 15 #define LL long long
 16 #define eps 1e-9
 17 #define PI acos(-1.0)
 18 using namespace std;
 19 const int INF = 0x3f3f3f3f;
 20 const int maxn = 210;
 21 
 22 double p[maxn];
 23 double a[maxn][maxn];//增广矩阵
 24 double X[maxn];//解集
 25 int num[maxn];//给每个能给到达的point离散化
 26 int n,m,x,y,d;
 27 int equ,var,cnt;
 28 
 29 bool Gauss()
 30 {
 31     int row,col,max_r,i,j;
 32     row = 0;
 33     col = 0;
 34     while(row < equ && col < var)
 35     {
 36         max_r = row;
 37         for(i = row+1; i < equ; i++)
 38         {
 39             if(fabs(a[i][col]) > fabs(a[max_r][col]))
 40                 max_r = i;
 41         }
 42         if(max_r != row)
 43         {
 44             for(j = col; j <= var; j++)
 45                 swap(a[row][j], a[max_r][j]);
 46         }
 47         if(fabs(a[row][col]) < eps)
 48         {
 49             col++;
 50             continue;
 51         }
 52         for(i = row+1; i < equ; i++)
 53         {
 54             if(fabs(a[i][col]) < eps) continue;
 55             double t = a[i][col]/a[row][col];
 56             a[i][col] = 0.0;
 57             for(j = col+1; j <= var; j++)
 58                 a[i][j] -= a[row][j]*t;
 59         }
 60         row++;
 61         col++;
 62     }
 63 
 64     for(i = row; i < equ; i++)
 65         if(fabs(a[i][var]) > eps)
 66             return false; //无解
 67     for(i = equ-1; i >= 0; i--)
 68     {
 69         if(fabs(a[i][i]) < eps) continue;
 70         double t = a[i][var];
 71         for(j = i+1; j < var; j++)
 72             t -= a[i][j]*X[j];
 73         X[i] = t/a[i][i];
 74     }
 75     return true;
 76 }
 77 
 78 void bfs(int s) //bfs找出所有能够到达的点并离散化
 79 {
 80     queue <int> que;
 81     que.push(s);
 82     num[s] = cnt++;
 83     while(!que.empty())
 84     {
 85         int u = que.front();
 86         que.pop();
 87         for(int i = 1; i <= m; i++)
 88         {
 89             if(fabs(p[i]) < eps)
 90                 continue;
 91             int v = (u+i)%n;
 92             if(num[v] == -1)
 93             {
 94                 num[v] = cnt++;
 95                 que.push(v);
 96             }
 97         }
 98     }
 99 }
100 
101 int main()
102 {
103     int test;
104     scanf("%d",&test);
105     for(int item = 1; item <= test; item++)
106     {
107         scanf("%d %d %d %d %d",&n,&m,&y,&x,&d);
108         for(int i = 1; i <= m; i++)
109         {
110             scanf("%lf",&p[i]);
111             p[i] /= 100;
112         }
113         if(x == y)
114         {
115             printf("0.00\n");
116             continue;
117         }
118         n = 2*(n-1);
119         if(d == 1)
120             x = n-x;
121         memset(num,-1,sizeof(num));
122         cnt = 0;
123         bfs(x);
124         if(num[y] == -1 && num[n-y] == -1) //注意这里是 &&,只有当两个方向都走不到才算走不到
125         {
126             printf("Impossible !\n");
127             continue;
128         }
129 
130         memset(a,0,sizeof(a));
131         memset(X,0,sizeof(X));
132         equ = var = cnt;
133 
134         for(int i = 0; i < n; i++)
135         {
136             if(num[i] != -1)
137             {
138                 if(i == y || i == n-y) //注意特判终点
139                 {
140                     a[num[i]][num[i]] = 1;
141                     a[num[i]][cnt] = 0;
142                     continue;
143                 }
144                 a[num[i]][num[i]] = 1;
145                 for(int j = 1; j <= m; j++)
146                 {
147                     int t = (i+j)%n;
148                     if(num[t] != -1)
149                         a[num[i]][num[t]] -= p[j];
150                     a[num[i]][cnt] += j*p[j];
151                 }
152             }
153         }
154         if(Gauss())
155             printf("%.2lf\n",X[num[x]]);
156         else printf("Impossible !\n");
157     }
158     return 0;
159 }

 

posted @ 2014-10-20 22:40  haohaooo  阅读(208)  评论(0编辑  收藏  举报