HDU 4870 Rating 多校联合练习赛 高斯消元

56 篇文章 0 订阅
3 篇文章 0 订阅



= =貌似其他人没贴详细列的过程。。 这里列一下。。

直接列成这样的式子。

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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值