Gym - 101606F Flipping Coins (概率dp,多种解法)

版权声明:本文为蒟蒻原创文章,转载请注明出处哦~ https://blog.csdn.net/a54665sdgf/article/details/82668258

题目链接

题意:有n枚硬币,一开始全部背面朝上,每次可以选择一枚硬币将其抛掷一次,求重复k次后,正面朝上的硬币个数的期望值。

记忆化搜索(dfs):

#define FRER() freopen("i.txt","r",stdin)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=400+10;
int n,k;
double d[N][N];

double dp(int now,int heads)
{
    if(now==k)return heads;
    if(d[now][heads]>=0)return d[now][heads];
    if(heads<n)return d[now][heads]=(dp(now+1,heads)+dp(now+1,heads+1))/2;
    return d[now][heads]=(dp(now+1,heads)+dp(now+1,heads-1))/2;
}

int main()
{
    scanf("%d%d",&n,&k);
    memset(d,200,sizeof d);
    printf("%f\n",dp(0,0));
    return 0;
}

递推(自底而上):

#define FRER() freopen("i.txt","r",stdin)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=400+10;
int n,k;
double d[N][N],ans;

int main()
{
    scanf("%d%d",&n,&k);
    for(int j=0;j<=n;++j)d[k][j]=j;
    for(int i=k-1;i>=0;--i)
    for(int j=0;j<=n;++j)
    {
        if(j<n)d[i][j]=(d[i+1][j]+d[i+1][j+1])/2;
        else d[i][j]=(d[i+1][j]+d[i+1][j-1])/2;
    }
    printf("%f\n",d[0][0]);
    return 0;
}

滚动数组优化后:

#define FRER() freopen("i.txt","r",stdin)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=400+10;
int n,k;
double d[2][N],ans;

int main()
{
    scanf("%d%d",&n,&k);
    for(int j=0;j<=n;++j)d[k&1][j]=j;
    for(int i=k-1;i>=0;--i)
    for(int j=0;j<=n;++j)
    {
        if(j<n)d[i&1][j]=(d[(i^1)&1][j]+d[(i^1)&1][j+1])/2;
        else d[i&1][j]=(d[(i^1)&1][j]+d[(i^1)&1][j-1])/2;
    }
    printf("%f\n",d[0][0]);
    return 0;
}

递推(自顶而下):

#define FRER() freopen("i.txt","r",stdin)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=400+10;
int n,k;
double d[N][N],ans;

int main()
{
    scanf("%d%d",&n,&k);
    d[0][0]=1;
    for(int i=0; i<k; ++i)
        for(int j=0; j<=n; ++j)
        {
            if(j<n)d[i+1][j]+=d[i][j]/2,d[i+1][j+1]+=d[i][j]/2;
            else d[i+1][j]+=d[i][j]/2,d[i+1][j-1]+=d[i][j]/2;
        }
    double ans=0;
    for(int j=0; j<=n; ++j)ans+=d[k][j]*j;
    printf("%f\n",ans);
    return 0;
}

滚动数组优化后:

#define FRER() freopen("i.txt","r",stdin)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=400+10;
int n,k;
double d[2][N],ans;

int main()
{
    scanf("%d%d",&n,&k);
    d[0][0]=1;
    for(int i=0; i<k; ++i)
    {
        memset(d[(i^1)&1],0,sizeof d[(i^1)&1]);
        for(int j=0; j<=n; ++j)
        {
            if(j<n)d[(i^1)&1][j]+=d[i&1][j]/2,d[(i^1)&1][j+1]+=d[i&1][j]/2;
            else d[(i^1)&1][j]+=d[i&1][j]/2,d[(i^1)&1][j-1]+=d[i&1][j]/2;
        }
    }
    double ans=0;
    for(int j=0; j<=n; ++j)ans+=d[k&1][j]*j;
    printf("%f\n",ans);
    return 0;
}

bfs:

#define FRER() freopen("i.txt","r",stdin)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=400+10;
int n,k;
double d[N][N],ans;
int vis[N][N];

struct node
{
    int a,b;
    node(int a,int b):a(a),b(b) {}
};

void update(int a,int b,double add,queue<node>& q)
{
    d[a][b]+=add;
    if(!vis[a][b])
    {
        vis[a][b]=1;
        q.push(node(a,b));
    }
}

void bfs()
{
    queue<node> q;
    q.push(node(0,0));
    d[0][0]=1;
    while(!q.empty())
    {
        int a=q.front().a,b=q.front().b;
        q.pop();
        if(a==k)return;
        if(b<n)update(a+1,b,d[a][b]/2,q),update(a+1,b+1,d[a][b]/2,q);
        else update(a+1,b,d[a][b]/2,q),update(a+1,b-1,d[a][b]/2,q);
    }
}

int main()
{
    scanf("%d%d",&n,&k);
    bfs();
    double ans=0;
    for(int j=0; j<=n; ++j)ans+=d[k][j]*j;
    printf("%f\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/a54665sdgf/article/details/82668258