hdu - 4326 - Game - 概率dp

本题题意很简单,给出n个人每次4人进行比赛其他人等待,胜者继续,负者排到最后,连续或得m次胜利的人成为最终的赢家,求第k个人最终获得胜利的概率是多少?

对于这题,我们首先确立一个这样的模型: x1先赢了i局,正在于x2,x3,x4赌斗,后面依次有x5,x6,……,xn等待。用P[i][j]表示x1先赢了i局的情况下,当前的xj获胜的概率。

http://acm.hdu.edu.cn/showproblem.php?pid=4326
i < m

P[i][j] = P[i + 1][j] * 1/4 + P[1][n - 2] * 3/4 j = 1

P[i + 1][n - 2] * 1/4 + P[1][1] * 1/4 + P[1][n - 1] * 2/4 j = 2

P[i + 1][n - 1] * 1/4 + P[1][1] * 1/4 + P[1][n - 1] * 1/4 + P[1][n] * 1/4 j = 3

P[i + 1][n] * 1/4 + P[1][1] * 1/4 + P[1][n] * 2/4 j = 4

P[i + 1][j - 3] * 1/4 + P[1][j - 3] * 3/4 j >=4

i = m

P[i][j] = 1 j = 1

0 j != 1

运用分数形式的高斯消元解方程。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
using namespace std;

#define maxn 102
#define eps 1e-10
double g[maxn][maxn];
double x[maxn];
int n,m,k;

void add(int cnt,int i,int j,double val){
    int t=i*n+j;
    if(i==m){
        if(j==1)    g[cnt][n*m+1]+=-1.0*val;
        return;
    }
    g[cnt][t]+=val;
}

void gauss(int n,int m){
    int row,col,i,j,k;
    for(row=1,col=1;row<n,col<m;row++,col++){
        k=row;
        for(i=row+1;i<=n;i++)
            if(fabs(g[i][col])>fabs(g[k][col])) k=i;
        if(k!=row){
            for(i=col;i<=m;i++) swap(g[k][i],g[row][i]);
        }
        if(fabs(g[row][col])<eps)   continue;
        for(i=row+1;i<=n;i++){
            if(fabs(g[i][col])<eps) continue;
            double t=g[i][col]/g[row][col];
            g[i][col]=0.0;
            for(j=col+1;j<=m;j++)   g[i][j]-=t*g[row][j];
        }
    }
    for(i=n;i>=1;i--){
        x[i]=g[i][m];
        for(j=i+1;j<=n;j++)    x[i]-=x[j]*g[i][j];
        x[i]/=g[i][i];
    }
}

int main(){
    int i,j,cs,nn=0;
    scanf("%d",&cs);
    while(cs--){
        scanf("%d%d%d",&n,&m,&k);
        memset(g,0,sizeof(g));
        int cnt=0;
        for(i=0;i<m;i++)
            for(j=1;j<=n;j++){
                cnt++;
                add(cnt,i,j,1.0);
                if(j==1){
                    add(cnt,i+1,j,-0.25);
                    add(cnt,1,n-2,-0.75);
                }
                else if(j==2){
                    add(cnt,i+1,n-2,-0.25);
                    add(cnt,1,1,-0.25);
                    add(cnt,1,n-1,-0.5);
                }
                else if(j==3){
                    add(cnt,i+1,n-1,-0.25);
                    add(cnt,1,1,-0.25);
                    add(cnt,1,n-1,-0.25);
                    add(cnt,1,n,-0.25);
                }
                else if(j==4){
                    add(cnt,i+1,n,-0.25);
                    add(cnt,1,n,-0.5);
                    add(cnt,1,1,-0.25);
                }
                else{
                    add(cnt,i+1,j-3,-0.25);
                    add(cnt,1,j-3,-0.75);
                }
            }
        gauss(n*m,n*m+1);
        printf("Case #%d: %.6lf\n",++nn,x[k]);
    }
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值