您的位置:首页 > 其它

2011年北京区域赛I-Activation

2012-10-03 19:35 169 查看
开始做的时候无从下手,这题就是一个概率dp。很多的细节。dp[i][j]指的是在有j个人的时候Tomato排的位置为j这个状态时的概率。这个题需要考虑的就是循环的问题,第一是p1的循环,所以对p2,p3,p4的概率进行了修改使他们的和为1.然后就是每次第一个人都失败,所以对于dp[m]
的概率是每轮的概率和相加。还有一点就是dp[i][j]=dp[i+1][j+1]*p3+dp[i+1][j]*p2;因为是一个循环所以要对这个式子进行化简。先将最开始的值求出来。我先贴一个T掉的版本,这个版本更容易理解思路。

#include<cstdio>

#include<cstring>

#include<cmath>

using namespace std;

double dp[2010][2010];

double p(double a,int n){

 if(n==0)

  return 1.0;

 else{

  double cnt=p(a,n/2);

  if(n%2)

   return cnt*cnt*a;

  else

   return cnt*cnt;

 }

}

main(){

 double p1,p2,p3,p4;

 int n,m,k;

 while(scanf("%d%d%d%lf%lf%lf%lf",&n,&m,&k,&p1,&p2,&p3,&p4)!=-1){

  p2=p2/(1-p1);p3=p3/(1-p1);p4=p4/(1-p1);

  memset(dp,0,sizeof(dp));

  dp[m]
=1/(1-p(p2,n));

  for(int i=1;i<m;i++){

   dp[i]
=dp[m]
*p(p2,m-i);

  }

  for(int i=m+1;i<=n;i++){

   dp[i]
=dp[m]
*p(p2,n+m-i);

  }

  double ans=0;

  for(int j=n-1;j>=1;j--){

   double tmp=1-p(p2,j);

   for(int i=j;i>=1;i--){

    if(i==j){

     int c=i-1;

     for(int kk=0;kk<j;kk++){

      dp[i][j]+=dp[c%j+2][j+1]*p3*p(p2,kk);

      c++;

     }

     dp[i][j]=dp[i][j]/tmp;

 

    }

    else{

     if(!(i==1 && j==1)){

      dp[i][j]=(p2*(dp[i+1][j]*tmp-dp[i+1][j+1]*p3*(1-tmp)/p2)+dp[i+1][j+1]*p3)/tmp;

     }

     else{

      dp[1][1]=(dp[2][2]*p3)/(1-p2);

     }

    }

    if(i<=k)

     ans+=dp[i][j];

    //printf("%lf ",dp[i][j]);

   }

  // printf("\n");

  }

  for(int i=1;i<=k;i++){

   ans+=dp[i]
;

  }

  printf("%.5lf\n",ans*p4);

 }

}

后来通过变形,把这个式子改好了。

但是这道题还有一个坑就是p4==0的时候需要特判,因为这样我为此还WA了一次。

AC代码:

#include<cstdio>

#include<cstring>

#include<cmath>

using namespace std;

double dp[2010][2010];

double const eps=1e-5;

double p(double a,int n){

 if(n==0)

  return 1.0;

 else{

  double cnt=p(a,n/2);

  if(n%2)

   return cnt*cnt*a;

  else

   return cnt*cnt;

 }

}

main(){

 double p1,p2,p3,p4;

 int n,m,k;

 while(scanf("%d%d%d%lf%lf%lf%lf",&n,&m,&k,&p1,&p2,&p3,&p4)!=-1){

  if(p4<eps){

    printf("0.00000\n");

    continue;

  }

  

  p2=p2/(1-p1);p3=p3/(1-p1);p4=p4/(1-p1);

  memset(dp,0,sizeof(dp));

  dp[m]
=1/(1-p(p2,n));

  for(int i=1;i<m;i++){

   dp[i]
=dp[m]
*p(p2,m-i);

  }

  for(int i=m+1;i<=n;i++){

   dp[i]
=dp[m]
*p(p2,n+m-i);

  }

  double ans=0;double cnt=0;

  int c=n-2;

  for(int kk=0;kk<n-1;kk++){

   cnt+=dp[c%(n-1)+2]
*p3*p(p2,kk);

    c++;

  }

  for(int j=n-1;j>=1;j--){

   double tmp=1-p(p2,j);

   for(int i=j;i>=1;i--){

    if(i==j){

     dp[i][j]=cnt/tmp;

     cnt=0;

     cnt+=dp[i][j]*p3;

    }

    else{

     if(!(i==1 && j==1)){

      dp[i][j]=(p2*(dp[i+1][j]*tmp-dp[i+1][j+1]*p3*(1-tmp)/p2)+dp[i+1][j+1]*p3)/tmp;

     }

     else{

      dp[1][1]=(dp[2][2]*p3)/(1-p2);

     }

    }

    if(i<=k)

     ans+=dp[i][j];

    if(i!=1 && i!=j)

     cnt+=dp[i][j]*p3*p(p2,i-1);

    //printf("%lf ",dp[i][j]);

   }

   //printf("\n");

  }

  for(int i=1;i<=k;i++){

   ans+=dp[i]
;

  }

  printf("%.5lf\n",ans*p4);

 }

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  2010 c