【浮*光】#概率dp# 洛谷p2059 卡牌游戏

很有意思的概率dp问题...因为有相对性在里面,所以转移方法很巧妙。

#include <cmath>
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <vector>
#include <algorithm>
#include <stack>
#include <queue>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;

/*【p2059】卡牌游戏 
类似约瑟夫游戏,求每个玩家获胜的概率。*/

//【标签】概率dp + 状态设计 + 数学分析(相对性)

//f[i][j]表示还剩i个人时、当前相对庄家位置为j的人最终获胜、的概率。f[1][1]=1。
//枚举庄家抽到的牌k,即此时被淘汰的人的相对位置为c。下一局i-1个人,更新庄家。
//即:当c>j时,第j个人是新庄家之后的第i−c+j个人;当c<j时,第j个人-->第j−c个人。
//转移方程:f[i][j]=f[i][j]+f[i−1][i−c+j]÷m,c>j;f[i][j]=f[i][j]+f[i−1][j−c]÷m,c<j。 

void reads(int &x){
    int fx=1;x=0;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')fx=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s-'0');s=getchar();}
    x=x*fx;//正负号
}

int n,m,a[10019]; double f[1019][1019]; 

int main(){
    reads(n),reads(m); for(int i=1;i<=m;i++) reads(a[i]);
    f[1][1]=1; for(int i=2;i<=n;i++)
        for(int j=1;j<=i;j++) for(int k=1;k<=m;k++){
            int c=(a[k]%i==0)?i:(a[k]%i); //牌k,数字c
            //↑↑即a[k]%i,c为此局被淘汰的人的相对位置
            if(c>j) f[i][j]=f[i][j]+f[i-1][i-c+j]/m;
            if(c<j) f[i][j]=f[i][j]+f[i-1][j-c]/m;
    } for(int i=1;i<=n;i++) printf("%.2lf%% ",f[n][i]*100.0);
} //注意%的符号输出形式:在printf中要写成%% ↑↑

                             ——时间划过风的轨迹,那个少年,还在等你

猜你喜欢

转载自www.cnblogs.com/FloraLOVERyuuji/p/10396476.html