zoukankan      html  css  js  c++  java
  • 【loj6191】「美团 CodeM 复赛」配对游戏 概率期望dp

    题目描述

    n次向一个栈中加入0或1中随机1个,如果一次加入0时栈顶元素为1,则将这两个元素弹栈。问最终栈中元素个数的期望是多少。

    输入

    一行一个正整数 n 。

    输出

    一行一个实数,表示期望剩下的人数,四舍五入保留三位小数。

    样例输入

    10

    样例输出

    4.168


    题解

    概率期望dp

    显然任何时刻栈中的元素自底至顶一定是若干个0+若干个1。

    但是如果设状态$p[i][j][k]$表示前$i$次操作,栈中$j$个0,$k$个1的概率,复杂度是$O(n^3)$的,显然会TLE。

    注意到$0$的个数对状态转移是没有影响的,而期望在任何时刻都具有可加性,因此可以设$f[i][j]$表示前$i$次操作,栈中$j$个1的期望元素个数。

    那么直接考虑新加入一个是0还是1,看一下长度是增加还是减少即可。

    这里有一个问题:每次增加或减少的长度是多少?由于我们设的是总情况的期望,而期望等于 概率*权值 ,这种情况的权值为1,因此期望值就是这种情况的概率。

    所以还需要维护一个$p[i][j]$表示前$i$次操作,栈中$j$个1的概率。每次使用概率转移期望即可。

    时间复杂度$O(n^2)$

    #include <cstdio>
    #define N 2010
    double p[N][N] , f[N][N];
    int main()
    {
    	int n , i , j;
    	double ans = 0;
    	scanf("%d" , &n) , p[0][0] = 1;
    	for(i = 0 ; i < n ; i ++ )
    	{
    		p[i + 1][1] += p[i][0] / 2 , f[i + 1][1] += (f[i][0] + p[i][0]) / 2;
    		p[i + 1][0] += p[i][0] / 2 , f[i + 1][0] += (f[i][0] + p[i][0]) / 2;
    		for(j = 1 ; j < n ; j ++ )
    		{
    			p[i + 1][j + 1] += p[i][j] / 2 , f[i + 1][j + 1] += (f[i][j] + p[i][j]) / 2;
    			p[i + 1][j - 1] += p[i][j] / 2 , f[i + 1][j - 1] += (f[i][j] - p[i][j]) / 2;
    		}
    	}
    	for(i = 0 ; i <= n ; i ++ ) ans += f[n][i];
    	printf("%.3lf
    " , ans);
    	return 0;
    }
    
  • 相关阅读:
    十三、asp.net中Repeater控件用法笔记
    九、chart控件的使用(图表数据的展示)
    一、在开发数据同步系统中的开发问题:
    ubuntu编译最新版本WebKit
    android apk 防止反编译技术第四篇-对抗JD-GUI
    小菜学Chromium之OpenGL学习之二
    webkit浏览器常见开发问题
    Android图片开发内幕--基础篇
    【转载】Android Metro风格的Launcher开发系列第二篇
    world 替换+正则表达式命令
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/7744970.html
Copyright © 2011-2022 走看看