[报告]HDU 4418 Time travel

Abstract

HDU 4418 Time travel

概率 Markov链 高斯消元

 

Body

Source

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

Description

题意不太好懂……

一个人在数轴上来回走,每次以一定概率前进[1, M]步,如果停下来的地方是目标就终止,否则继续该过程直到在目标停下。求走过的路程的期望。

Solution

读明白了就可以发现其实是个比较明显的概率高斯消元题。

首先把(pos,dir)全部展开成一维的坐标,把往回走的方向翻折到另一边即可。这样就有2*(N-1)个点。

令K=2*(N-1),写出期望方程

e[pos] = sigma{i from 1 to m} (e[(pos+i)%K]+i)*p[i]

边界为e[t]=e[(K-t)%K]=0。

高斯消元解之求e[s]即可。但是tricky的地方就在这里。看以下这组数据:

4 2 2 0 -1

0 100

答案应该为2,而高斯消元解出来的结果是no solution。原因就在于有些状态从s开始走是根本访问不到的,同时也访问不到t,也就是这些状态和整个markov过程根本无关。这些状态之间构成的方程无解就会导致整个解向量不存在,但并不代表e[s]不存在。解决的办法就是将这些状态的期望强制设为INF。判断某个状态能否访问到用bfs就可以了。

Code

#include <iostream>

#include <cassert>

#include <cmath>

#include <cstdio>

#include <cstring>

#include <queue>

#include <algorithm>

using namespace std;



const double EPS = 1e-8;



inline int sgn(double d) {

    if (fabs(d)<EPS) return 0;

    return d>0?1:-1;

}



int gauss(int N, int M, double a[][222]) {

    int i, j, r, c, pvt;

    double maxp;

    for (r=0, c=0; r<N && c<M; ++r, ++c) {

        for (maxp=0, i=r; i < N; ++i)

            if (fabs(a[i][c])>fabs(maxp)) maxp = a[pvt=i][c];

        if (sgn(maxp)==0) {

            r--;

            continue;

        }

        if (pvt != r)

            for (j = r; j <= M; ++j) swap(a[r][j], a[pvt][j]);

        for (j = c+1; j <= M; ++j) {

            a[r][j] /= maxp;

            for (i = r+1; i < N; ++i)

                a[i][j] -= a[i][c]*a[r][j];

        }

    }

    for (i = r; i < N; ++i)

        if (sgn(a[i][M])) return -1;

    if (r < M) return M-r;

    for (i = M-1; i >= 0; --i)

        for (j = i+1; j < M; ++j)

            a[i][M] -= a[j][M]*a[i][j];

    return 0;

}



int T, N, M, s, t, d;

double a[222][222];

double p[111];



int vis[222];



bool bfs(int s) {

    queue<int> q;

    q.push(s);

    memset(vis, 0, sizeof vis);

    vis[s] = 1;

    while (!q.empty()) {

        int u = q.front();

        q.pop();

        for (int i = 0; i < M; ++i) {

            u++; if (u==N) u = 0;

            if (sgn(p[i]) && !vis[u]) {

                vis[u] = 1;

                q.push(u);

            }

        }

    }

    if (vis[t] || vis[(N-t)%N]) return 1;

    else return 0;

}



int main() {

    int i, j, k, r, c;

    cin>>T;

    while (T--) {

        cin>>N>>M>>t>>s>>d;

        assert(N!=0);

        for (i = 0; i < M; ++i) {

            cin>>p[i];

            p[i] /= 100;

        }

        N = N-1<<1;

        if (d > 0) s = N-s;

        if (s==t) {

            puts("0.00");

            continue;

        }

        if (!bfs(s)) {

            puts("Impossible !");

            continue;

        }

        double sum = 0;

        for (i = 0; i < M; ++i)

            sum += p[i]*(i+1);

        memset(a, 0, sizeof a);

        for (i = 0; i < N; ++i) {

            a[i][i] = 1;

            if (!vis[i]) {

                a[i][N] = 1e9;

                continue;

            }

            if (i==t||i==(N-t)%N) {

                a[i][N] = 0;

                continue;

            }

            a[i][N] = sum;

            int now = i;

            for (j = 0; j < M; ++j) {

                now++; if (now==N) now = 0;

                a[i][now] -= p[j];

            }

        }

        if (~gauss(N, N, a)) {

            printf("%.2f\n", a[s][N]+EPS);

        }

        else puts("Impossible !");

    }

    return 0;

}

你可能感兴趣的:(time)