lightoj1151 Snakes and Ladders:概率DP+高斯消元

lightoj1151

题意:

  • 有100个格子,从1开始走,每次随机走1~6。有n个格子会单向传送到其他格子,tp[i]表示从i传送到tp[i]。 
  • 1和100不会有传送,一个格子也不会有两种传送。问走到100投色子的期望值,注意不能走到100以外。

题解

  • dp[i]表示从i到100的还需要的期望次数
  • 如果有传送门,那么dp[i] = dp[v[i]]
  • 如果没有传送门:dp[i] = 1/6 * ∑(dp[i+j] + 1)(j from 1 to k) + 1/6 * ∑(dp[i] + 1)(j from k+1 to 6),其中k = min(100-i,6); 
  • 化简得到:k * dp[i] - ∑dp[i+j] = 6 (j from 1 to k)
  • 联立方程组
  • k * dp[i] - ∑dp[i+j] = 6 (j from 1 to k)
  • dp[i] = dp[v[i]]
  • 高斯消元求解dp[1]

代码

#include <bits/stdc++.h>
using namespace std;
int const N = 100 + 10;
int n,v[N];
double a[N][N];
void SwapRow(double a[][N],int n,int p,int q){
    for(int i=p;i<=n+1;i++)
        swap(a[p][i],a[q][i]);
}
void SelectColE(double a[][N],int n){
    for(int i=1;i<=n-1;i++){
        int MaxRowE = i;
        for(int j=i;j<=n;j++)
            if(fabs(a[j][i]) > fabs(a[MaxRowE][i]))  MaxRowE = j;
        if(i != MaxRowE)    SwapRow(a,n,i,MaxRowE);
        for(int j=i+1;j<=n;j++){
            double temp = a[j][i] / a[i][i];
            for(int k=i;k<=n+1;k++)
                a[j][k] -= a[i][k] * temp;
        }
    }
}
void Back_Substitution(double a[][N],int n){
    for(int i=n;i>=1;i--)
    {
        for(int j=i+1;j<=n;j++)
            a[i][n+1] -=a[i][j] * a[j][n+1];
        a[i][n+1] /=a[i][i];
    }
}
void Gauss_Elimination(double a[][N],int n){
    SelectColE(a,n);
    Back_Substitution(a,n);
}
int main(){
	int T,caser = 0;
	scanf("%d",&T);
	while(T--){
		scanf("%d",&n);
		memset(v,0,sizeof(v));
		for(int i=1;i<=n;i++){
			int x,y;
			scanf("%d%d",&x,&y);
			v[x] = y;
		}
		memset(a,0,sizeof(a));
		a[100][100] = 1;   //表示E[100] = 0;所有加上系数  初始化
		for(int i=1;i<100;i++){
			if(v[i]){   //如果发生跳转
				a[i][i] = 1;
				a[i][v[i]] = -1;
			}else{  //如果不跳转
				int k = min(6,100 - i);
				a[i][i] = k;
				for(int j=1;j<=k;j++)
					a[i][i+j] = -1;
				a[i][101] = 6;
			}
		}
	    Gauss_Elimination(a,100);
		printf("Case %d: %.6lf\n",++caser,a[1][101]);
	}
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值