zoukankan      html  css  js  c++  java
  • [JLOI2013] 卡牌游戏

    题目链接:https://www.luogu.org/problemnew/show/P2059

    概率DP。

    我们设计状态为(sum[i][j])表示还剩下i个人的时候,从庄家开始数第(j)个人获胜的概率(不包括庄家)。

    之后就是状态转移了。我们先考虑顺推,但是发现不太可做,因为还有删除节点的情况存在。删除总没有添加好做,所以我们考虑倒着推。

    首先我们要知道——如果有情况A有m的概率发生,且它们有n的概率直接转换成情况B,那么B情况发生的概率可加上(m imes n)

    我们定义庄家的位置为:(pos)

    我们定义当前的淘汰者的位置为:(pos+c)

    (j)的位置为:(pos+j)

    那么显然,(j>c)的时候,(j)的位置是(i-1)个人的新环中新庄家开始数的第(j-c-1)个人(不包括庄家)

    (j==c)的时候,第(j)个人一定会输,所以不累加胜率。

    (j<c)的时候,第(j)个人的位置是(i-1)人新环中新庄家开始数的第(i-(pos+c-pos-j)-1=i-c+j-1)个人。(不包括庄家)

    初始化:很显然的,当还剩一个人的时候,他一定是必胜的。所以(sum[1][0]=1.0)

    所以状态转移方程为:

    if(j>c)
    	sum[i][j]+=sum[i-1][j-c-1]/m;
    else if(j<c)
    	sum[i][j]+=sum[i-1][i-c+j-1]/m;
    

    完整代码如下:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #define MAXN 55
    using namespace std;
    int n,m;
    int a[MAXN];
    double sum[MAXN][MAXN];
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=m;i++)
    		scanf("%d",&a[i]),a[i]--;
    	sum[1][0]=1;
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=0;j<i;j++)
    		{
    			for(int k=1;k<=m;k++)
    			{
    				int c=(a[k]%i==0)?i:a[k]%i;
    				if(j>c) sum[i][j]+=sum[i-1][j-c-1]/m;
    				else if(j<c) sum[i][j]+=sum[i-1][i-c+j-1]/m;
    			}
    		}
    	}
    	for(int i=1;i<=n;i++)
    		printf("%.2lf%% ",sum[n][i-1]*100);
    	return 0;
    }
    
  • 相关阅读:
    iOS中的imageIO与image解码
    在asp.net 中生成PDF的方法
    asp.net中模拟测试smtp发邮件
    ASP.NET导入EXCEL方法汇总
    在asp.net中使用加密数据库联接字符串
    CSS实现限制字数功能
    在ASP.NET中备份和还原数据库
    说说ASP.NET的IsPostBack
    javascript小技巧之with()方法
    CSS中filter滤镜的学习笔记
  • 原文地址:https://www.cnblogs.com/fengxunling/p/9867038.html
Copyright © 2011-2022 走看看