HDU 4418 Time travel(高斯消元+概率DP)

来源:互联网 发布:小米6陶瓷版 知乎 编辑:程序博客网 时间:2024/05/17 03:23


  题意:一个人在数轴上来回走,以pi的概率走i步i∈[1, m],给定n(数轴长度),m,e(终点),s(起点),d(方向),求从s走到e经过的点数期望。

  思路:先把n(n>1)个点展开成2*n-2个点,这一步的作用是简化方向这个状态,使得现在所有点在一条直线上,例如原来是01234321,现在展开成了01234567.

设dp[i]为当前在i点走到目标点的期望步数,根据状态转移可以得到若干方程

但是,这些方程里有些是不合法的,所以会导致结果错误,

这是因为,对于一个点来说,可能从起点走不到这个点,但是方程组里我们还是保留了这些方程,这样的话结果计算出来就会错误,所以在开始时我们可以一次bfs将所有能到达的点标记并重新编号,然后计算这些点的状态转移方程。

#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#include<iostream>#include<algorithm>#include<vector>#include<map>#include<queue>#include<stack>#include<string>#include<map>#include<set>#include<ctime>#define eps 1e-9#define LL long long#define pii pair<int, int>//#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;int n, m, Y, X, d;const int MAXN=220;double p[MAXN];double a[MAXN][MAXN],x[MAXN];//方程的左边的矩阵和等式右边的值,求解之后x存的就是结果,行列编号从0开始 int equ,var;//方程数和未知数个数int num[MAXN];int Gauss() {    int i,j,k,col,max_r;    for(k=0,col=0;k<equ&&col<var;k++,col++) {        max_r=k;        for(i=k+1;i<equ;i++)          if(fabs(a[i][col])>fabs(a[max_r][col]))            max_r=i;        if(fabs(a[max_r][col])<eps)return 0;        if(k!=max_r) {            for(j=col;j<var;j++)              swap(a[k][j],a[max_r][j]);            swap(x[k],x[max_r]);        }        x[k]/=a[k][col];        for(j=col+1;j<var;j++)a[k][j]/=a[k][col];        a[k][col]=1;        for(i=0;i<equ;i++)          if(i!=k) {              x[i]-=x[k]*a[i][k];              for(j=col+1;j<var;j++)a[i][j]-=a[k][j]*a[i][col];              a[i][col]=0;          }    }    return 1;}int bfs() {queue<int> q;q.push(X);int cnt = 0;memset(num, -1, sizeof(num));num[X] = cnt++;while(!q.empty()) {int t = q.front(); q.pop();for(int i = 1; i <= m; i++) {if(fabs(p[i]) < eps) continue;int id = (t+i)%n;if(num[id] == -1) {num[id] = cnt++;q.push(id);}} }return cnt;} int main() {    //freopen("input.txt", "r", stdin);int T; cin >> T;while(T--) {int tmp;scanf("%d%d%d%d%d", &tmp, &m, &Y, &X, &d);for(int i = 1; i <= m; i++) scanf("%lf", &p[i]), p[i]/=100;n = 2*tmp - 2;if(!n) n+=1;if(d>0) X = n - X;equ = var = bfs();if(num[Y]==-1 && num[n-Y]==-1) { printf("Impossible !\n");continue;}memset(x, 0, sizeof(x));memset(a, 0, sizeof(a));for(int i = 0; i < n; i++) {if(num[i]==-1) continue;a[num[i]][num[i]] = 1.0;if(i==Y || i==n-Y) continue;for(int j = 1; j <= m; j++) {int id = (i+j) % n;if(num[id] != -1) {a[num[i]][num[id]] -= p[j];x[num[i]] += j*p[j];}}}if(Gauss()) printf("%.2f\n", x[num[X]]);else printf("Impossible !\n");}    return 0;}

0 0