zoj 3582 DP 求期望
dp[i][j]表示一边亮i个洞,一边亮j个洞到达成目标还需的天数
显然dp[i][j](i>=m,j>=m)=0;
dp[i][j]和dp[i+a][j+b]形成递推关系所以需要枚举i,j以及a、b的所有组合数复杂度为O(n^4)
注意每个灯亮与不亮都是独立的
四个for循环
View Code
#include<cstdio>
#include<cstring>
const int maxn = 55 ;
double dp[maxn][maxn];
double c[maxn][maxn];
double mulp[maxn];
double mul_p[maxn];
double P;
int m,n;
void init()
{
for(int i=0;i<maxn;i++){
c[i][0]=1;
c[i][i]=1;
for(int j=1;j<i;j++)
c[i][j]=c[i-1][j-1]+c[i-1][j];
}
}
int main()
{
int i,j;
init();
while(scanf("%d%d%lf",&n,&m,&P),(n||m))
{
mulp[0]=1;
for(i=1;i<=n;i++) mulp[i]=mulp[i-1]*P;
mul_p[0]=1;
for(i=1;i<=n;i++) mul_p[i]=mul_p[i-1]*(1.0-P);
memset(dp,0,sizeof(dp));int a,b;
for(i=n;i>=0;i--)
{
for(j=n;j>=0;j--)
{
if(i>=m&&j>=m) continue;
double sum=0;
for(a=0;a+i<=n;a++)
{
for(b=0;b+j<=n;b++)
{
if(a==0&&b==0) continue;
if(n-i>=a&&n-j>=b)
sum+=dp[a+i][b+j]*c[n-i][a]*mulp[a]*mul_p[n-i-a]*c[n-j][b]*mulp[b]*mul_p[n-j-b];
}
}
dp[i][j]=(sum+1)/(1-mul_p[n-i]*mul_p[n-j]);
}
}
printf("%.6lf\n",dp[0][0]);
}
}
记忆化搜索 dp[i][j]表示当前两边分别有有i个暗亮j个洞暗要完成目标还需要的天数
View Code
#include<cstdio>
#include<cstring>
const int maxn = 55 ;
double dp[maxn][maxn];
double c[maxn][maxn];
double mulp[maxn];
double mul_p[maxn];
double P;
int N,M;
void init(){
for(int i=0;i<maxn;i++){
c[i][0]=1;
c[i][i]=1;
for(int j=1;j<i;j++)
c[i][j]=c[i-1][j-1]+c[i-1][j];
}
}
double DP(int n,int m){
if(dp[n][m]>=0)return dp[n][m];
if(N-n>=M&&N-m>=M)return dp[n][m]=0;
double sum=0;
int i,j;
for(i=0;i<=n;i++)for(j=0;j<=m;j++){
if(i==0&&j==0)continue;
sum+=DP(n-i,m-j)*mulp[i]*mul_p[n-i]*c[n][i]*mulp[j]*mul_p[m-j]*c[m][j];
}
dp[n][m]=(sum+1)/(1-mul_p[n]*mul_p[m]);
return dp[n][m];
}
int main()
{
int i,j;
init();
while(scanf("%d%d%lf",&N,&M,&P),(N||M)){
mulp[0]=1;
for(i=1;i<=N;i++) mulp[i]=mulp[i-1]*P;
mul_p[0]=1;
for(i=1;i<=N;i++) mul_p[i]=mul_p[i-1]*(1.0-P);
memset(dp,-1,sizeof(dp));
double ans=DP(N,N);
printf("%.6lf\n",ans);
}
return 0;
}