poj2096 Collecting bugs 概率dp
链接:http://poj.org/problem?id=2096
大意就是讲:n种bug,s个子区域,每天随机在某个区域找一种,问期望找全的时间。
考虑每一种状态,对于每一个f[i][j](表示找了i种,j个区域),在下一天有四种转移可能:
1、在没找过的区域中找到一种没出现过的bug,即转移到f[i+1][j+1],这样做的可能性为{((n-i)/n)*((s-j)/s)},记为s1。
2、在没找过的区域中找到一种出现过的bug,即转移到f[i][j+1],可能性为{(i/n)*((s-j)/s)},记为s2。
3、在找过的区域中找到一种没出现过的bug,即转移到f[i+1][j],可能性为{((n-i)/n)*(j/s)},记为s3。
4、在找过的区域中找到一种出现过的bug,即停留在f[i][j],可能性为{(i/n)*(j/s)},记为s4。
那么转移方程就是f[i][j]=f[i+1][j+1]*s1+f[i][j+1]*s2+f[i+1][j]*s3+f[i][j]*s4+1,
化简可以得到f[i][j]=(f[i+1][j+1]*s1+f[i][j+1]*s2+f[i+1][j]*s3+1)/(1-s4),这也就是倒推期望的式子。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 using namespace std; 7 const int maxn=1005; 8 int n,s; 9 double dp[maxn][maxn],p1,p2,p3,p4; 10 int haha() 11 { 12 while(scanf("%d%d",&n,&s)!=EOF) 13 { 14 memset(dp,0,sizeof(dp)); 15 for(int i=n;i>=0;i--) 16 for(int j=s;j>=0;j--) 17 { 18 if(i==n&&j==s)continue; 19 p1=(n-i)*(s-j)*1.0; 20 p2=(n-i)*j*1.0; 21 p3=i*(s-j)*1.0; 22 p4=n*s-i*j*1.0; 23 dp[i][j]=(p1*dp[i+1][j+1]+p2*dp[i+1][j]+p3*dp[i][j+1]+n*s)/p4; 24 } 25 printf("%.4lf\n",dp[0][0]); 26 } 27 return 0; 28 } 29 int sb=haha(); 30 int main(){;}
只要是活着的东西,就算是神我也杀给你看。