Codeforces 28C Bath Queue 【计数类DP】*
Codeforces 28C Bath Queue
简要题意:有 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 }