bzoj 3270 博物馆 高斯消元

题面

题目传送门

解法

\((x,y)\)表示第一个人在\(x\)房间,第二个人在\(y\)房间,然后列一个方程组即可

直接用高斯消元解一下就行了

时间复杂度:\(O(n^6)\)

代码

#include <bits/stdc++.h>
#define double long double
#define eps 1e-9
#define N 410
using namespace std;
int n, m, cnt, s[N], f[N][N];
double p[N], a[N][N];
int calc(int x, int y) {return (x - 1) * n + y;}
void gauss(int n) {
    for (int i = 1; i <= n; i++) {
        if (fabs(a[i][i]) < eps)
            for (int j = i + 1; j <= n; j++)
                if (fabs(a[j][i]) > eps)
                    for (int k = 1; k <= n + 1; k++) swap(a[i][k], a[j][k]);
        for (int j = i + 1; j <= n + 1; j++) a[i][j] /= a[i][i];
        for (int j = 1; j <= n; j++) {
            if (i == j) continue;
            for (int k = i + 1; k <= n + 1; k++)
                a[j][k] -= a[j][i] * a[i][k];
        }
    }
}
int main() {
    ios::sync_with_stdio(false);
    cin >> n >> m; int sx, sy;
    cin >> sx >> sy; cnt = n;
    for (int i = 1; i <= m; i++) {
        int x, y; cin >> x >> y;
        f[x][y] = f[y][x] = 1;
        s[x]++, s[y]++;
    }
    a[calc(sx, sy)][n * n + 1] = 1;
    for (int i = 1; i <= n; i++) cin >> p[i], f[i][i] = 1;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++) {
            a[calc(i, j)][calc(i, j)] = 1;
            for (int x = 1; x <= n; x++)
                for (int y = 1; y <= n; y++)
                    if (x != y && f[x][i] && f[y][j]) {
                        double p1 = (x == i) ? p[x] : (1 - p[x]) / s[x];
                        double p2 = (y == j) ? p[y] : (1 - p[y]) / s[y];
                        a[calc(i, j)][calc(x, y)] -= p1 * p2;
                    }
            }
    gauss(n * n);
    for (int i = 1; i <= n; i++)
        cout << fixed << setprecision(6) << a[calc(i, i)][n * n + 1] << ' ';
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/copperoxide/p/9476709.html