Rating【概率dp+高斯消元】

本文解析了VJudge上的一道难题,通过将问题转化为比赛得分的形式,利用动态规划和高斯消元法求解期望比赛场数。代码实现展示了如何设置线性方程组并求解,最终得到两个账号分别从0分到20分的期望比赛次数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:https://vjudge.net/problem/HDU-4870

将问题转换为每次可能+1分,-2分,目标到达20分。

且最终状态一定是一个账号19分,另一个账号20分。

因为期望的线性性,所以可以对两个账号分别计算期望,然后求和。

dp[u]表示以u分开始,到达20分的期望比赛场数,那么有dp[u] = p*(dp[u+1]+1) + (1-p)*(dp[u-2]+1)

那么最终答案就是dp[0]+dp[0]-dp[19]。

这题卡了精度,而且方程一定有解,所以高斯消元就不判断无解情况了。

(ps:对dp方程进行一下变形后,这题可以O(n)线性递推解决)

#include <bits/stdc++.h>
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define per(i, a, b) for(int i = (a); i >= (b); i--)
#define pb push_back
using namespace std;
const int N = 450;
const double eps = 1e-7;
double a[N][N],ans[N];
bool gauss(int n) {
    rep(i, 0, n-1) {          //逐列消除
        int p = i;
        rep(j, i+1, n-1)          //找到该列最大系数所在的行p,减少误差(也可以找第一个非0系数,但误差会大一些)
            if(fabs(a[p][i])<fabs(a[j][i]))
                p = j;

      
        swap(a[i],a[p]);        //否则把p交换上来,用其进行消元

        double div = a[i][i];
        rep(j, i, n) a[i][j] /= div;  //把p的第i列系数置1
        rep(j, 0, n-1)  {                 //开始消其他行
            if(i==j) continue;
            div = a[j][i];
            rep(k, i, n)
                a[j][k] -= a[i][k]*div;
        }
    }
    rep(i, 0, n-1) ans[i] = a[i][n];
    return 1;
}
int main() {
   // freopen("a.txt","r",stdin);
    double p;
    while(cin>>p) {
        memset(a,0,sizeof(a));
        rep(i, 0, 19) {
            a[i][i] += 1;
            a[i][i+1] += -p;
            a[i][max(i-2,0)] += -(1-p);
            a[i][21] += 1;
        }
        a[20][20] += 1;
        a[20][21] += 0;
        gauss(21);
        printf("%.8f\n",ans[0]+ans[0]-ans[19]);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值