配对游戏(概率DP)
链接:https://ac.nowcoder.com/acm/problem/13333
来源:牛客网
题目描述
美团点评是综合性生活服务平台,覆盖吃喝玩乐。在休闲娱乐版块,有很多轰趴、桌游、密室逃脱类的项目,适合多人一起玩。下面就是出自团队游戏场景中的一个问题。
有 n 个人排成一排,一开始全部面向前方,然后大家一起转身,随机朝左或是朝右转。
转身后,不断检查队列,如果存在两个面对面的相邻的人,则将这两个人从队列中消除;直到不存在两个面对面的相邻的人。
例如 > 表示向右, < 表示向左
队列“>>><<<”的消除过程为,“>>><<<”到“>><<”到“><”到“”(每次去除一对),最后剩下人数为0。
队列“>><><<<>”的消除过程为,“>><><<<>”到“>><<<>”到“><<>”到“<>”(每次去除一对),最后剩下人数为2
求最后剩下人数的期望值。
有 n 个人排成一排,一开始全部面向前方,然后大家一起转身,随机朝左或是朝右转。
转身后,不断检查队列,如果存在两个面对面的相邻的人,则将这两个人从队列中消除;直到不存在两个面对面的相邻的人。
例如 > 表示向右, < 表示向左
队列“>>><<<”的消除过程为,“>>><<<”到“>><<”到“><”到“”(每次去除一对),最后剩下人数为0。
队列“>><><<<>”的消除过程为,“>><><<<>”到“>><<<>”到“><<>”到“<>”(每次去除一对),最后剩下人数为2
求最后剩下人数的期望值。
输入描述:
一行一个正整数 n (1 ≤ n ≤ 2000)。
输出描述:
一行一个实数,表示剩下人数的期望值,四舍五入保留三位小数。
示例1
输出
复制4.168
这里提供两种解题思路(见代码)
#include<bits/stdc++.h>
using namespace std;
const int maxn=2005;
double dp[maxn][maxn];//前i个人还有j个人向右消除了的期望数
double dp1[maxn][maxn];//达到dp[i][j]的概率
/*
考虑第i个人:
如果他向右那么dp[i][j+1] += dp[i-1][j]/2 dp1[i][j+1] += dp1[i-1][j]/2
如果他向左那么dp[i][j-1] += dp[i-1][j]/2 + dp1[i-1][j] dp1[i][j-1] += dp1[i-1][j]/2
注意j为0的时候
*/
const double tem=0.5;
double ans[maxn];
int main(){
dp1[0][0]=1;
for(int i=1;i<maxn;i++){
for(int j=0;j<i;j++){
dp[i][j+1] += dp[i-1][j]*tem;
dp1[i][j+1] += dp1[i-1][j]*tem;
if(j>0){
dp[i][j-1] += dp[i-1][j]*tem+dp1[i-1][j];
dp1[i][j-1] += dp1[i-1][j]*tem;
}
else{
dp[i][j] += dp[i-1][j]/2;
dp1[i][j] += dp1[i-1][j]/2;
}
}
}
for(int i=1;i<maxn;i++){
ans[i]=i;
for(int j=0;j<=i;j++){
ans[i]-=dp[i][j];
}
}
int n;
while(scanf("%d",&n)!=EOF)
printf("%.3lf\n",ans[n]);
return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int maxn=2005;
double dp[maxn][maxn];//前i个人还有j个人向右剩下的期望数
double dp1[maxn][maxn];//达到dp[i][j]的概率
/*
考虑第i个人:
如果他向右那么dp[i][j+1] += dp[i-1][j]/2+dp1[i-1][j] dp1[i][j+1] += dp1[i-1][j]/2
如果他向左那么dp[i][j-1] += dp[i-1][j]/2 - dp1[i-1][j] dp1[i][j-1] += dp1[i-1][j]/2
注意j为0的时候
*/
const double tem=0.5;
double ans[maxn];
int main(){
dp1[0][0]=1;
for(int i=1;i<maxn;i++){
for(int j=0;j<i;j++){
dp[i][j+1] += dp[i-1][j]*tem + dp1[i-1][j];
dp1[i][j+1] += dp1[i-1][j]*tem;
if(j>0){
dp[i][j-1] += dp[i-1][j]*tem - dp1[i-1][j];
dp1[i][j-1] += dp1[i-1][j]*tem;
}
else{
dp[i][j] += dp[i-1][j]/2;
dp1[i][j] += dp1[i-1][j]/2;
}
}
}
for(int i = 1;i < maxn; i++){
for(int j = 0;j <= i;j++){
ans[i] += dp[i][j];
}
}
int n;
while(scanf("%d",&n)!=EOF)
printf("%.3lf\n",ans[n]);
return 0;
}

浙公网安备 33010602011771号