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;
}

posted @ 2018-08-14 18:48  谜のNOIP  阅读(118)  评论(0编辑  收藏  举报