HDU 1204 糖果大战【概率】

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1204

设dp[i]为当前Speakless所拥有的的糖果数为i时的概率。

于是可以得到以下转移:

·赢了:概率为p*(1-q),会将p*(1-q)*dp[i]转移给dp[i+1]

·输了:概率为(1-p)*q,会将(1-p)*q*dp[i]转移给dp[i-1]

·平局:概率为p*1+(1-p)*(1-q),会将p*q+(1-p)*(1-q)转移给dp[i]

其中dp[0]和dp[n+m]为终点状态,不需要转移出去。

dp[n]为起点状态,视为将1.0转移给dp[n]。

看了一眼数据规律,懒得推公式了,直接高斯消元搞一波即可。

注意输出负0的情况。

代码:

#include <bits/stdc++.h>

using namespace std;

#define sfi(a) scanf("%d",&a)
#define sfd(a) scanf("%lf",&a)
#define sfl(a) scanf("%lld",&a)
#define sfs(a) scanf("%s",a)

#define rep(i,a,b) for(int i=int(a);i<int(b);++i)
#define dwn(i,b,a) for(int i=int(b-1);i>=int(a);--i)

#define mem(a,p) memset(a,p,sizeof(a))

typedef long long LL;
typedef unsigned UINT;
typedef unsigned long long ULL;

#define eps 0
#define MAXN 105

struct Gauss
{
    double a[MAXN][MAXN];	//输入的矩阵 
    int n;
    
    int res;	//解空间的维数 
    
    bool l[MAXN];	//表示第i个解是否为自由元 
    double ans[MAXN];	//方程组的解 
    
    inline void init(int nn)
    {
        n=nn;
        mem(a,0);
    }
    
    inline void update(int x,int y,double p)	//令矩阵中的a[x][y]加上p 
    {
        a[x][y]+=p;
    }
    
    inline void print()	//调试用方法 
    {
        rep(i,0,n)
        {
            rep(j,0,n+1)printf("%.3lf ",a[i][j]);
            printf("\n");
        }
        printf("\n");
    }
    
    inline void solve()	//生成解以及自由元判定 
    {
        res=0;
        int r=0;
        rep(i,0,n)l[i]=false;
        rep(i,0,n)
        {
            rep(j,r,n)if(fabs(a[j][i])>eps)
            {
                rep(k,i,n+1)swap(a[j][k],a[r][k]);
                break;
            }
            if(fabs(a[r][i])<eps)
            {
                ++res;
                continue;
            }
            rep(j,0,n)if(j!=r&&fabs(a[j][i])>eps)
            {
                double tmp=a[j][i]/a[r][i];
                rep(k,i,n+1)a[j][k]-=tmp*a[r][k];
            }
            l[i]=true,++r;
        }
        rep(i,0,n)
            if(l[i])
                rep(j,0,n)
                    if(fabs(a[j][i])>0)
                        ans[i]=a[j][n]/a[j][i];
    }
}G;

int main()
{
	int n,m;
	while(sfi(n)==1)
	{
		sfi(m);
		G.init(n+m+1);
		G.update(n,n+m+1,-1);
		double p,q;
		sfd(p);
		sfd(q);
		rep(i,0,n+m+1)
		{
			G.update(i,i,-1.0);
			if((i==0)||(i==n+m))continue;
			G.update(i,i,p*q+(1.0-p)*(1.0-q));
			G.update(i-1,i,(1-p)*q);
			G.update(i+1,i,p*(1-q));
		}
		G.solve();
		printf("%.2lf\n",G.ans[n+m]+1e-8);
	}
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值