Codeforces 28C Bath Queue 【计数类DP】*

Codeforces 28C Bath Queue


LINK


简要题意:有 n 个人等概率随机进入 m 个房间,一个房间可以有多个人,第 i 个房间有 ai 个水龙头,在一个房间的人要去排队装水,他们会使得最长的队尽可能小,求所有房间中最长队列长度的期望

Mark一个很好的blog



 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 110
 4 #define fu(a,b,c) for(int a=b;a<=c;++a)
 5 #define fd(a,b,c) for(int a=b;a>=c;--a)
 6 double dp[N][N][N]={0};
 7 double c[N][N]={0};
 8 int a[N],n,m;
 9 int main(){
10     scanf("%d%d",&n,&m);
11     fu(i,1,m)scanf("%d",&a[i]);
12     fu(i,0,n+m)c[i][0]=1;
13     fu(i,1,n+m)
14         fu(j,1,i)
15             c[i][j]=c[i-1][j-1]+c[i-1][j];
16     fu(i,0,m)dp[i][0][0]=1;
17     fu(i,1,m)
18         fu(j,1,n)
19             fu(k,0,j){
20                 //case1: 当前的房间到达上线
21                 int l=max(a[i]*(k-1)+1,0),r=a[i]*k;
22                 fu(w,0,k)
23                     fu(p,l,min(r,j))
24                         dp[i][j][k]+=dp[i-1][j-p][w]*c[n-j+p][p];
25                 //case2: 前面某个房间到达上限
26                 fu(p,0,min(l-1,j))
27                     dp[i][j][k]+=dp[i-1][j-p][k]*c[n-j+p][p];
28             }
29     double ans=0;
30     fu(i,1,n)ans+=dp[m][n][i]*i;
31     fu(i,1,n)ans/=(double)m;
32     printf("%.10lf",ans);
33     return 0;
34 }
原文地址:https://www.cnblogs.com/dream-maker-yk/p/9676277.html