【BZOJ3270】博物馆

题意:给定一张无向连通图,两个人初始各在某个点上,每个时刻每个人会不动或任选出边走,求两人最终期望在哪里相遇

 

PoPoQQQ的解法:http://blog.csdn.net/popoqqq/article/details/44777907

 

我的解法

状态表示为f[k][i][j]  表示第K步第一人在i第二人在j

按步数划分阶段,对于每个阶段f[k][i][j]可以由f[k - 1][p][q]推出来

要求的东西是 sigma i = 1..oo (f[i][V][V])

所以可以把所有阶段的方程(矩阵)直接加起来,消去阶段(步数)这一维

对于K=1 方程只有一行 1= f[a][b]

最后的方程形如

for_each (i, j)

  for_each (k, l)

    sigma p[(k, l) to (i, j)] * x[k][l] = x[i][j]

特别的

  for_each (k, l)

    sigma p[(k, l) to (a, b)] * x[k][l] + 1 = x[a][b]

 

#include <cstdio>
#include <cmath>
#include <iostream>
using namespace std;
const int N = 410;
int n, m, a, b;
double map[N][N], p[N][N];
bool g[N][N];
int out[N];
void gauss(int n, double a[N][N]) {
    int i, j, k, r;
    for (i = 0; i < n; i ++) {
        r = i;
        for (j = i + 1; j < n; j ++)
            if (fabs(a[j][i]) > fabs(a[r][i])) r = j;
        if (r != i) for (j = 0; j <= n; j ++) swap(a[r][j], a[i][j]);
        for (k = i + 1; k < n; k ++) {
            double f = a[k][i] / a[i][i];
            for (j = i; j <= n; j ++) a[k][j] -= f * a[i][j];
        }
    }
    for (i = n - 1; i >= 0; i --) {
        for (j = i + 1; j < n; j ++)
            a[i][n] -= a[j][n] * a[i][j];
        a[i][n] /= a[i][i];
    }
}
             
         
int main() {
    scanf("%d%d%d%d", &n, &m, &a, &b);
    a --; b --;
    for (int i = 1, u, v; i <= m; i ++) {
        scanf("%d%d", &u, &v);
        u --; v --;
        g[u][v] = g[v][u] = 1;
        out[u] ++;
        out[v] ++;
    }
    for (int i = 0; i < n; i ++)
        scanf("%lf", &map[i][i]);
    for (int i = 0; i < n; i ++)
        for (int j = 0; j < n; j ++) {
            if (i == j) continue;
            if (g[i][j] == false)
                map[i][j] = 0;
            else
                map[i][j] = (1.0 - map[i][i]) / out[i];
        }
    for (int i = 0; i < n; i ++)
        for (int j = 0; j < n; j ++)
            for (int k = 0; k < n; k ++)
                for (int l = 0; l < n; l ++) {
                    int u = n * i + j;
                    int v = n * k + l;
                    if (k != l)
                        p[u][v] = map[k][i] * map[l][j];
                    else
                        p[u][v] = 0;
                }
    for (int i = 0; i < n * n; i ++)
        p[i][i] -= 1;
    p[n * a + b][n * n] = -1;
    gauss(n * n, p);
    for (int i = 0; i < n; i ++)
        printf("%.6lf ", p[n * i + i][n * n]);
    putchar(10);
    return 0;
}

 

posted @ 2015-06-16 14:14  Moretimes  阅读(341)  评论(0编辑  收藏  举报