版权声明:本文为蒟蒻原创文章,转载请注明出处哦~ 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;
}