HDU--2262(高斯消元,概率DP)

2015-04-13 22:49:30

思路:参考了爱神的博客A的... 也改善了下高斯的模板。

  首先给每个格子编号,假设某个格子(设为第 i 个)到终点的期望为Ei,考虑第 i 格的所有可行后继节点(可行节点的意思是这些后继节点可以到达终点)

  记为En1,En2....Enk,总共k个,可列方程:Ei = (En1+En2+En3+ ... + Enk) / k + 1

  转化为:En1+En2+En3+ ... + k*Eni = -k

  如此这样可以列出 n*m 条方程,高斯消元求出主元即可。终点的方程稍特殊:1*Eed = 0

  关于求可行后继节点,可以从每个终点(注意,可能有多个出口)开始bfs求出。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <cmath>
  5 #include <vector>
  6 #include <map>
  7 #include <set>
  8 #include <stack>
  9 #include <queue>
 10 #include <string>
 11 #include <iostream>
 12 #include <algorithm>
 13 using namespace std;
 14 
 15 #define MEM(a,b) memset(a,b,sizeof(a))
 16 #define REP(i,n) for(int i=0;i<(n);++i)
 17 #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
 18 #define getmid(l,r) ((l) + ((r) - (l)) / 2)
 19 #define MP(a,b) make_pair(a,b)
 20 
 21 typedef long long ll;
 22 typedef pair<int,int> pii;
 23 const int INF = (1 << 30) - 1;
 24 const int MAXN = 20;
 25 const int MAXM = 250;
 26 const double eps = 1e-9;
 27 
 28 int n,m,top;
 29 char g[MAXN][MAXN];
 30 double A[MAXM][MAXM];
 31 bool can[MAXN][MAXN];
 32 int dir[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};
 33 
 34 void Bfs(){
 35     MEM(can,false);
 36     queue<int> x,y;
 37     while(!x.empty()) x.pop();
 38     while(!y.empty()) y.pop();
 39     REP(i,n) REP(j,m) if(g[i][j] == '$'){
 40         x.push(i);
 41         y.push(j);
 42         can[i][j] = true;
 43     }
 44     while(!x.empty()){
 45         int curx = x.front(); x.pop();
 46         int cury = y.front(); y.pop();
 47         for(int k = 0; k < 4; ++k){
 48             int tx = curx + dir[k][0];
 49             int ty = cury + dir[k][1];
 50             if(tx >= 0 && tx < n && ty >= 0 && ty < m && g[tx][ty] != '#'){
 51                 if(can[tx][ty] == false){
 52                     can[tx][ty] = true;
 53                     x.push(tx);
 54                     y.push(ty);
 55                 }
 56             }
 57         }
 58     }
 59 }
 60 
 61 bool Gauss(){
 62     int i,col;
 63     for(i = 0,col = 0; col < top; ++i,++col){
 64         int r = i;
 65         for(int j = i + 1; j < top; ++j)
 66             if(fabs(A[j][col]) > fabs(A[r][col])) r = j;
 67         if(r != i) for(int j = col; j <= top; ++j) swap(A[r][j],A[i][j]);
 68         if(fabs(A[i][col]) < eps){
 69             --i;
 70             continue;
 71         }
 72         for(int j = top; j >= col; --j) A[i][j] /= A[i][col];
 73         for(int k = 0; k < top; ++k) if(k != i)
 74             for(int j = top; j >= col; --j)
 75                 A[k][j] -= A[k][col] * A[i][j];
 76     }
 77     for(; i < top; ++i) if(!(fabs(A[i][top]) < eps)) return false;
 78     return true;
 79 }
 80 
 81 int main(){
 82     while(scanf("%d%d",&n,&m) != EOF){
 83         top = n * m;
 84         REP(i,n) scanf("%s",g[i]);
 85         REP(i,top) REP(j,top + 1) A[i][j] = 0.0;
 86         Bfs();
 87         int sx,sy;
 88         REP(i,n) REP(j,m) if(g[i][j] == '@'){
 89             sx = i;
 90             sy = j;
 91             break;
 92         }
 93         REP(i,n) REP(j,m) if(g[i][j] != '#'){
 94             int a = i * m + j;
 95             if(g[i][j] == '$'){
 96                 A[a][top] = 0;
 97                 A[a][a] = 1;
 98                 continue;
 99             }
100             int cnt = 0;
101             REP(k,4){
102                 int tx = i + dir[k][0];
103                 int ty = j + dir[k][1];
104                 if(tx >= 0 && tx < n && ty >= 0 && ty < m
105                         && g[tx][ty] != '#' && can[tx][ty]){
106                     A[a][tx * m + ty] = 1;
107                     cnt++;
108                 }
109             }
110             A[a][a] = A[a][top] = -1.0 * cnt;
111         }
112         if(can[sx][sy] && Gauss()){
113             //找主元
114             for(int i = 0; i < top; ++i){
115                 if(fabs(A[i][sx * m + sy] - 1.0) < eps){
116                     printf("%.6f\n",A[i][top]);
117                     break;
118                 }
119             }
120         }
121         else printf("-1\n");
122     }
123     return 0;
124 }

 

posted @ 2015-04-13 23:09  Naturain  阅读(175)  评论(0编辑  收藏  举报