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

2015-04-16 12:21:13

思路:这道题琢磨了很久....

  题意比较晦涩:给一个0~N-1的数列,有一个起点,有初始方向,在数列里面走,如果碰到边界就换方向。再给出每次走 i (i<=M) 步的概率,问走到终点的期望步数。

  先是自己YY了一个拆点的方法,乱搞了一天... 过了样例但是跑不过一些特殊数据... wa 弃疗

  看了别人的博客...

  核心点:

  (1)将N个点扩张成:2×(N-1)个点,N =2*(N-1)

     如:01234 -> 01234321,这样以来只用往右走:

      此时“右走”在4的左边(01234)代表右走,在4的右边(4321)代表左走,所以根据方向确定起点后就不用再管方向,一律右走。

     所以如果起始方向为左,则 X = (N - X) % N

  (2)首先要从起点 / (终点)跑一遍 bfs 来判断某些点是否能从起点到达 / (能否到达终点)。注意起点只有一个,而终点有两个!

  (3)剩下的就是经典的带环概率DP问题了,用高斯消元求解

    Ei = E(i+1)*P1 + E(i+2)*P2 + E(i+3)*P3 + ... + E(i+M)*PM + 1

    -> -Ei + E(i+1)*P1 + E(i+2)*P2 + E(i+3)*P3 + ... + E(i+M)*PM = -1

  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 = 210;
 25 const double eps = 1e-8;
 26 
 27 int T;
 28 int N,M,Y,X,D;
 29 double P[MAXN];
 30 double g[MAXN][MAXN];
 31 bool can[MAXN];
 32 
 33 void Gauss(){
 34     int i,col;
 35     for(i = 0,col = 0; col < N; ++i,++col){
 36         int r = i;
 37         for(int j = i + 1; j < N; ++j)
 38             if(fabs(g[j][col]) > fabs(g[r][col])) r = j;
 39         if(r != i) for(int j = col; j <= N; ++j) swap(g[r][j],g[i][j]);
 40         if(fabs(g[i][col]) < eps){
 41             --i;
 42             continue;
 43         }
 44         for(int j = N; j >= col; --j) g[i][j] /= g[i][col];
 45         for(int k = 0; k < N; ++k) if(k != i){
 46             for(int j = N; j >= col; --j)
 47                 g[k][j] -= g[k][col] * g[i][j];
 48         }
 49     }
 50 }
 51 
 52 void Debug(){
 53     for(int i = 0; i < N; ++i){
 54         for(int j = 0; j <= N; ++j) printf("%.2f ",g[i][j]);
 55         puts("");
 56     }
 57 }
 58 
 59 void Bfs(){
 60     queue<int> Q;
 61     while(!Q.empty()) Q.pop();
 62     MEM(can,false);
 63     can[Y] = can[(N - Y) % N] = true;
 64     Q.push(Y);
 65     Q.push((N - Y) % N);
 66     while(!Q.empty()){
 67         int cur = Q.front(); Q.pop();
 68         FOR(j,1,M){
 69             int nxt = (cur - j + N) % N;
 70             if(P[j] >= eps && !can[nxt]){
 71                 can[nxt] = true;
 72                 Q.push(nxt);
 73             }
 74         }
 75     }
 76 }
 77 
 78 int main(){
 79     scanf("%d",&T);
 80     while(T--){
 81         MEM(g,0);
 82         scanf("%d%d%d%d%d",&N,&M,&Y,&X,&D);
 83         FOR(i,1,M) scanf("%lf",&P[i]),P[i] /= 100.0;
 84         if(X == Y){
 85             printf("0.00\n");
 86             continue;
 87         }
 88         N = (N - 1) * 2;
 89         if(D > 0) X = (N - X) % N;
 90         Bfs();
 91         if(!can[X]){
 92             printf("Impossible !\n");
 93             continue;
 94         }
 95         REP(i,N){
 96             if(i == Y || i == (N - Y) % N){
 97                 g[i][i] = 1;
 98                 g[i][N] = 0;
 99                 continue;
100             }
101             g[i][i] = -1;
102             FOR(j,1,M){
103                 int nxt = (i + j) % N;
104                 if(!can[nxt]) continue;
105                 g[i][nxt] += P[j];
106                 g[i][N] -= j * P[j];
107             }
108         }
109         //Debug();
110         Gauss();
111         for(int i = 0; i < N; ++i) if(fabs(g[i][X]-1) < eps){
112             printf("%.2f\n",g[i][N]);
113             break;
114         }
115     }
116     return 0;
117 }

 

... YY后的尸体,勿念 TAT

  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 = 210;
 25 const double eps = 1e-8;
 26 
 27 int T;
 28 int N,M,Y,X,D,NN;
 29 double P[MAXN];
 30 double g[MAXN * 2][MAXN * 2];
 31 bool can[MAXN * 2];
 32 
 33 bool Gauss(){
 34     int i,col;
 35     for(i = 0,col = 0; col < NN; ++i,++col){
 36         int r = i;
 37         for(int j = i + 1; j < NN; ++j)
 38             if(fabs(g[j][col]) > fabs(g[r][col])) r = j;
 39         if(r != i) for(int j = col; j <= NN; ++j) swap(g[r][j],g[i][j]);
 40         if(fabs(g[i][col]) < eps){
 41             --i;
 42             continue;
 43         }
 44         for(int j = NN; j >= col; --j) g[i][j] /= g[i][col];
 45         for(int k = 0; k < NN; ++k) if(k != i){
 46             for(int j = NN; j >= col; --j)
 47                 g[k][j] -= g[k][col] * g[i][j];
 48         }
 49     }
 50     for(; i < NN; ++i) if(!(fabs(g[i][NN]) < eps)) return false;
 51     return true;
 52 }
 53 
 54 void Debug(){
 55     for(int i = 0; i < NN; ++i){
 56         for(int j = 0; j <= NN; ++j) printf("%.2f ",g[i][j]);
 57         puts("");
 58     }
 59 }
 60 
 61 void Bfs(){
 62     queue<int> Q;
 63     while(!Q.empty()) Q.pop();
 64     MEM(can,false);
 65     can[Y << 1] = can[Y << 1|1] = true;
 66     Q.push(Y << 1);
 67     Q.push(Y << 1|1);
 68     while(!Q.empty()){
 69         int cur = Q.front(); Q.pop();
 70         int cur_pos = cur / 2;
 71         FOR(j,1,M){
 72             int tj = j % (2 * N);
 73             int pos;
 74             int f = cur & 1;
 75             if((!f && cur_pos == N - 1) || (f && cur_pos == 0)) f ^= 1;
 76             if(!f){
 77                 pos = cur_pos + tj;
 78                 if(pos >= N) pos = 2*N - pos - 2,f ^= 1;
 79                 if(pos < 0) pos = -pos,f ^= 1;
 80                 if(pos >= N) pos = 2*N - pos - 2,f ^= 1;
 81                 if(pos < 0) pos = -pos,f ^= 1;
 82             }
 83             else{
 84                 pos = cur_pos - tj;
 85                 if(pos < 0) pos = -pos,f ^= 1;
 86                 if(pos >= N) pos = 2*N - pos - 2,f ^= 1;
 87                 if(pos < 0) pos = -pos,f ^= 1;
 88                 if(pos >= N) pos = 2*N - pos - 2,f ^= 1;
 89             }
 90             pos = pos << 1|f;
 91             if(!can[pos]){
 92                 can[pos] = true;
 93                 Q.push(pos);
 94             }
 95         }
 96     }
 97 }
 98 
 99 int main(){
100     scanf("%d",&T);
101     while(T--){
102         MEM(g,0);
103         scanf("%d%d%d%d%d",&N,&M,&Y,&X,&D);
104         NN = N << 1;
105         FOR(i,1,M) scanf("%lf",&P[i]),P[i] /= 100.0;
106         if(X == Y){
107             printf("0.00\n");
108             continue;
109         }
110         Bfs();
111         if(can[X << 1|D] == false){
112             printf("Impossible !\n");
113             continue;
114         }
115         //for(int i = 0; i < NN; ++i)
116         //    printf("can[%d] : %d\n",i,can[i]);
117         REP(i,N){
118             if(i == Y){
119                 g[i << 1][i << 1] = 1;
120                 g[i << 1][NN] = 0;
121                 g[i << 1|1][i << 1|1] = 1;
122                 g[i << 1|1][NN] = 0;
123                 continue;
124             }
125             g[i << 1][i << 1] = -1;
126             g[i << 1|1][i << 1|1] = -1;
127             FOR(j,1,M){ //走j步
128                 int tj = j % (2 * N);
129                 int pos,f = 0;
130                 //向右走到i
131                 pos = i + tj;
132                 if(pos >= N) pos = 2*N - pos - 2,f ^= 1; //next position
133                 if(pos < 0) pos = -pos,f ^= 1;
134                 if(pos >= N) pos = 2*N - pos - 2,f ^= 1; //next position
135                 if(pos < 0) pos = -pos,f ^= 1;
136                 
137                 //printf("i : %d , pos : %d\n",i,pos);
138                 //if(pos == 0 && f == 1) pos = pos << 1;
139                 //else if(pos == N - 1 && f == 0) pos = pos << 1|1;
140                 //else 
141                 pos = pos << 1|f;
142                 if(can[pos]){
143                     g[i << 1][pos] += P[j];
144                     g[i << 1][NN] -= j * P[j];
145                 }
146                 //向左走到i
147                 f = 1;
148                 pos = i - tj;
149                 if(pos < 0) pos = -pos,f ^= 1; //next position
150                 if(pos >= N) pos = 2*N - pos - 2,f ^= 1;
151                 if(pos < 0) pos = -pos,f ^= 1; //next position
152                 if(pos >= N) pos = 2*N - pos - 2,f ^= 1;
153                 
154                 //printf("i : %d , pos : %d\n",i,pos);
155                 //if(pos == 0 && f == 1) pos = pos << 1;
156                 //else if(pos == N - 1 && f == 0) pos = pos << 1|1;
157                 //else 
158                 pos = pos << 1|f;
159                 if(can[pos]){
160                     g[i << 1|1][pos] += P[j];
161                     g[i << 1|1][NN] -= j * P[j];
162                 }
163             }
164         }
165         //Debug();
166         if(Gauss()){
167             for(int i = 0; i < NN; ++i) if(fabs(g[i][X << 1|D]-1) < eps){
168                 //printf("row : %d\n",i);
169                 printf("%.2f\n",g[i][NN]);
170                 break;
171             }
172         }
173         else printf("Impossible !\n");
174     }
175     return 0;
176 }
View Code

 

posted @ 2015-04-16 12:43  Naturain  阅读(174)  评论(0编辑  收藏  举报