牛客--卡牌游戏 (概率DP 逆推) P2059

题目链接:卡牌游戏

n个人,m张卡牌上有m个数字。庄家随机一张卡牌,数字为X,第X位出局,随后第X位的下一位做庄家,问,每个人最后获胜的概率是多少?

约瑟夫环的变形问题,这里每次等概率的抽牌,数字相对于定值来说是随机的,
dp[i][j]: 还剩i个人时,第j个人获胜的概率 。
初始状态 : dp[1][1]=1.0 最后剩下的那个人获胜
从游戏的结局向前推,剩i人时,枚举m张卡牌,计算出下一局他的位置(剩i-1人时)(庄家位置变化后,每个人的相对位置都会改变,因此需要计算),累加。我们算的是第j个人获胜的概率,如果刚好抽到他自己出局,忽略不计。

抽到出局的位置temp:
1,temp=j ,忽略
2,temp < j 时,他下一局的位置 j-temp;累加 dp[i-1][j-temp]
3,temp > j 时,他下一局的位置 i-temp+j;累加 dp[i-1] [i-temp+j]

最后输出 dp[n][1 : n] * 100;

#include<bits/stdc++.h>
#define ll long long
#define db double
using namespace std;
const int maxx=100;

double  dp[maxx][maxx];
int a[maxx];

int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1; i<=m; i++)
        scanf("%d",&a[i]);
    dp[1][1]=1.0;
    for(int i=2; i<=n; i++)
        for(int j=1; j<=i; j++)
            for(int k=1; k<=m; k++)
            {
                int temp=a[k]%i==0 ? i:a[k]%i;
                if(temp>j)
                    dp[i][j]+=(dp[i-1][i-temp+j]/(double)m);
                else if(temp<j)
                    dp[i][j]+=(dp[i-1][j-temp]/(double)m);

            }
            char ch='%';
        for(int i=1;i<=n;i++)
           printf("%.2lf%c ",dp[n][i]*100,ch);

    return 0;

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值