= =貌似其他人没贴详细列的过程。。 这里列一下。。
直接列成这样的式子。
f[0][0] = p * (f[1][0]) + (1-p) * f[0][0] + 1
f[1][0] = p * (f[1][1]) + (1-p) * f[1][0] + 1
f[1][1] = p * (f[2][1]) + (1-p) * f[1][0] + 1
f[2][1] = p * (f[2][2]) + (1-p) * f[2][0] + 1
f[2][2] = p * (f[3][2]) + (1-p) * f[2][0] + 1
f[3][2] = p * (f[3][3]) + (1-p) * f[3][0] + 1
f[3][0] = p * (f[3][1]) + (1-p) * f[3][0] + 1
....
f[19][19] = p * (f[20][19]) + (1-p) * f[19][17] + 1
之后将所有的 f 移到左边
得到
f[0][0] - p * (f[1][0]) - (1-p) * f[0][0] = 1
f[1][0] - p * (f[1][1]) -(1-p) * f[1][0] = 1
f[1][1] - p * (f[2][1]) - (1-p) * f[1][0] = 1
f[2][1] - p * (f[2][2]) - (1-p) * f[2][0] = 1
f[2][2] - p * (f[3][2]) - (1-p) * f[2][0] = 1
f[3][2] - p * (f[3][3]) - (1-p) * f[3][0] = 1
f[3][0] - p * (f[3][1]) - (1-p) * f[3][0] = 1
....
f[19][19] - p * (f[20][19]) - (1-p) * f[19][17] = 1
之后设 f[0][0] 为 x1, f[1][0]为x2, f[2][1]为 x3。。。
一条式子 , 200多个点,, 就只有4个点可能不是0.
左边这些f, 分别取出它的系数, 构造出矩阵 g[][], 右边常数项作为 b[]矩阵
之后进行LUP分解, 之后线性回归解出答案。。
#include <cstdio>
#include <cassert>
#include <cstring>
#include <cmath>
#include <map>
#include <algorithm>
#include <iostream>
using namespace std;
map<pair<int,int> ,int> S;
int n;
// u >= v;
const int N = 210;
void dfs(int x, int y) {
if(x != 20 && !S.count(std::make_pair(x, y))) {
S[std::make_pair(x, y)] = n++;
dfs(std::max(x, std::min(y + 1, 20)), std::min(x, std::min(y + 1, 20)));
dfs(x, std::max(y - 2, 0));
}
}
double p,g[N][N],b[N];
int at(int x, int y) {
int s = std::max(x, y);
int t = std::min(x, y);
if(s == 20) {
return -1;
}
return S[std::make_pair(s, t)];
}
const int MAXN = 210;
const double EPS = 1e-10;
int r[MAXN], c[MAXN];
void LU(int n, double a[MAXN][MAXN], int r[MAXN], int c[MAXN]) {
for (int i = 0; i < n; ++i) {
r[i] = c[i] = i;
}
for (int k = 0; k < n; ++k) {
int ii = k, jj = k;
for (int i = k; i < n; ++i) {
for (int j = k; j < n; ++j) {
if (fabs(a[i][j]) > fabs(a[ii][jj])) {
ii = i;
jj = j;
}
}
}
std::swap(r[k], r[ii]);
std::swap(c[k], c[jj]);
for (int i = 0; i < n; ++i) {
std::swap(a[i][k], a[i][jj]);
}
for (int j = 0; j < n; ++j) {
std::swap(a[k][j], a[ii][j]);
}
if (fabs(a[k][k]) < EPS) {
continue;
}
for (int i = k + 1; i < n; ++i) {
a[i][k] = a[i][k] / a[k][k];
for (int j = k + 1; j < n; ++j) {
a[i][j] -= a[i][k] * a[k][j];
}
}
}
}
void solve(int n, double a[MAXN][MAXN], int r[MAXN], int c[MAXN], double b[MAXN]) {
static double x[MAXN];
for (int i = 0; i < n; ++i) {
x[i] = b[r[i]];
}
for (int i = 0; i < n; ++i) {
for (int j = 0; j < i; ++j) {
x[i] -= a[i][j] * x[j];
}
}
for (int i = n - 1; i >= 0; --i) {
for (int j = n - 1; j > i; --j) {
x[i] -= a[i][j] * x[j];
}
if (fabs(a[i][i]) >= EPS) {
x[i] /= a[i][i];
} else assert(fabs(x[i]) < EPS);
}
for (int i = 0; i < n; ++i) {
b[c[i]] = x[i];
}
}
int main(){
S.clear();
n = 0;
dfs(0,0);
while(cin >> p){
memset(g,0,sizeof(g));
for(map<pair<int,int>,int>::iterator iter = S.begin(); iter != S.end(); iter++){
int x = (iter->first).first;
int y = (iter->first).second;
int from = iter->second;
int to = at(x, std::min(y + 1, 20));
if(to != -1) {
g[from][to] = -p;
}
to = at(x, std::max(y - 2, 0));
if(to != -1) {
g[from][to] = p-1;
}
b[from] = 1;
}
for(int i = 0;i < n;i++)
g[i][i] += 1;
LU(n,g,r,c);
solve(n,g,r,c,b);
printf("%.6lf\n",b[0]);
}
return 0;
}