首页 > 代码库 > BZOJ4008. [HNOI2015]亚瑟王 期望概率dp

BZOJ4008. [HNOI2015]亚瑟王 期望概率dp

看到这道题想什么? 一个好转移的状态由于T最多444所以把每个点控制在O(400000)以内,所以对于n和r最多乘一次因此猜f[n][r],f[r][n],首先一轮一轮的搞不好转移,那么先想一想f[n][r],如果是从头开始,在转移到下一位的时候,前面的会对后面的有恶心的影响,那么倒着来f[i][j]=(1.0-p[i])j*f[i+1][j]+[1.0-(1.0-p[i])j*(f[i+1][j-1]+d[i]),

#include<cstdio>
#include<cstring>
#include<iostream>
#define N 222
#define M 140
using namespace std;
typedef double D;
D p[N],t[N][M],f[N][M];
int n,r,d[N];
void Init()
{ 
   scanf("%d%d",&n,&r);
   for(int i=1;i<=n;i++)
   {
     scanf("%lf",&p[i]);
     scanf("%d",&d[i]);
     t[i][1]=1.0-p[i];
     for(int j=2;j<=r;j++)
      t[i][j]=t[i][j-1]*(1.0-p[i]);
   }
   for(int i=1;i<=r;i++)
     f[n][i]=(1.0-t[n][i])*d[n];
}
void work()
{
   for(int i=n-1;i>0;i--)
     for(int j=1;j<=r;j++)
      f[i][j]=t[i][j]*f[i+1][j]+(1.0-t[i][j])*(f[i+1][j-1]+d[i]);
   printf("%.10lf\n",f[1][r]);
}
int main()
{
   freopen("arthur.in","r",stdin);
   freopen("arthur.out","w",stdout);
   int T;
   scanf("%d",&T);
   while(T--)
   {
     Init();
     work();
   }
   return 0;
}

 

BZOJ4008. [HNOI2015]亚瑟王 期望概率dp