[报告]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;
}
posted @ 2012-09-24 22:03  杂鱼  阅读(1076)  评论(2编辑  收藏  举报