【Luogu】P2059卡牌游戏(概率DP)

  题目链接

  这绝壁是道紫难度的题

  请移步xyz32678的题解。

  设f[i][j]是有i个人参加了游戏,1是庄家,最后j胜出的概率。

  我们可以发现,这个游戏影响胜出的概率的只有庄家的相对位置和人数,跟玩家的具体编号是无关的。  于是我们可以枚举D,表示庄家目前抽到的牌值为D。

  则有if(d>j)  f[i][j]+=f[i-1][i-d+1]/m

  if(d<j)    f[i][j]+=f[i-1][j-d]/m

  这样子。最后f[n][i]就是玩家胜出的概率。

  发现写题解的过程有助于理解题解……

  代码放上。

  

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>

inline long long read(){
    long long num=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')    f=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        num=num*10+ch-'0';
        ch=getchar();
    }
    return num*f;
}

double f[100][100];
int q[1000];

int main(){
    int n=read(),m=read();
    for(int i=1;i<=m;++i)    q[i]=read();
    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 d=q[k]%i;    if(d==0)    d=i;
                if(d>j)    f[i][j]+=f[i-1][i-d+j]/m;
                if(d<j)    f[i][j]+=f[i-1][j-d]/m;
            }
    for(int i=1;i<=n;++i)    printf("%.2lf%% ",f[n][i]*100);
    return 0;
}

  xyz32768 爆强

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>

inline long long read(){
    long long num=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')    f=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        num=num*10+ch-'0';
        ch=getchar();
    }
    return num*f;
}

double f[100][100];
int q[1000];

int main(){
    int n=read(),m=read();
    for(int i=1;i<=m;++i)    q[i]=read();
    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 d=q[k]%i;    if(d==0)    d=i;
                if(d>j)    f[i][j]+=f[i-1][i-d+j]/m;
                if(d<j)    f[i][j]+=f[i-1][j-d]/m;
            }
    for(int i=1;i<=n;++i)    printf("%.2lf%% ",f[n][i]*100);
    return 0;
}

posted @ 2017-11-07 10:13  Konoset  阅读(238)  评论(0编辑  收藏  举报