AT_dp_j Sushi题解
题目描述
有 N 个盘子。每个盘子编号为 1,2,…,N。最初,对于每个 i(1≤i≤N),第 i 个盘子上有 ai(1≤ai≤3)个寿司。
太郎君会不断重复以下操作,直到所有寿司都被吃完:
- 掷一个等概率出现 1,2,…,N 的骰子,掷出的点数为 i。如果第 i 个盘子上还有寿司,则吃掉一个寿司;如果没有寿司,则什么也不做。
请你求出吃完所有寿司所需操作次数的期望值。
输入格式
输入从标准输入按以下格式给出。
N a1 a2 … aN
输出格式
输出吃完所有寿司所需操作次数的期望值。如果相对误差不超过 10−9,则视为正确。
显示翻译
题意翻译
输入输出样例
输入 #1复制
3 1 1 1
输出 #1复制
5.5
输入 #2复制
1 3
输出 #2复制
3
输入 #3复制
2 1 2
输出 #3复制
4.5
输入 #4复制
10 1 3 2 3 3 2 3 2 1 3
输出 #4复制
54.48064457488221
说明/提示
限制条件
- 输入均为整数。
- 1≤N≤300
- 1≤ai≤3
样例解释 1
吃掉第一个寿司所需操作次数的期望为 1。之后,吃掉第二个寿司所需操作次数的期望为 1.5。再之后,吃掉第三个寿司所需操作次数的期望为 3。因此,总的操作次数期望为 1+1.5+3=5.5。
样例解释 2
例如,输出 3.00、3.000000003、2.999999997 等也可以被判定为正确。
由 ChatGPT 4.1 翻译
思路
概率期望DP。
代码见下
#include<bits/stdc++.h>
using namespace std;
long long a[305],b[4];
double n,f[305][305][305],lk=0;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
b[a[i]]++;
}
sort(a+1,a+(long)n+1);
f[b[1]][b[2]][b[3]]=0;
for(int k=0;k<=n;k++){
for(int j=0;j<=n;j++){
for(int i=0;i<=n;i++){
if(i!=0||j!=0||k!=0){
if(i!=0){
f[i][j][k]+=(double)f[i-1][j][k]*i/(i+j+k);
}
if(j!=0){
f[i][j][k]+=(double)f[i+1][j-1][k]*j/(i+j+k);
}
if(k!=0){
f[i][j][k]+=(double)f[i][j+1][k-1]*k/(i+j+k);
}
f[i][j][k]+=(double)n/(i+j+k);
}
}
}
}
printf("%.15lf\n",f[b[1]][b[2]][b[3]]);
return 0;
}

浙公网安备 33010602011771号