bzoj 4008 [HNOI2015] 亞瑟王
阿新 • • 發佈:2018-08-30
first problem getchar += har long long inline ace pro
bzoj 4008 [HNOI2015] 亞瑟王
題面
[題面][https://www.lydsy.com/JudgeOnline/problem.php?id=4008]
題解
我們令\(f[i][j]\)表示當前考慮了前\(i\)張卡牌,前\(i\)張牌一共剩下\(j\)次機會的概率是多少
那麽\(f[0][r]=1\)
然後遞推地求解
如果第\(i+1\)張卡牌沒有用到 那麽\(f[i+1][j]+=f[i][j]\times (1-p[i+1])^j\)
如果第\(i+1\)張卡牌被用到了,那麽少了一次機會,多了一些傷害
\(f[i+1][j-1]+=f[i][j]\times (1-(1-p[i+1])^j)\)
然後答案會加\(f[i][j]\times(1-(1-p[i+1])^j)\times d[i+1]\)
就是概率乘傷害
Review
這題據TRCYX說是NewTrain最難得期望dp
我覺得主要是狀態難想,因為考慮到某一張牌只和前面的牌有關,和後面的牌無關,而且出牌的順序也不影響答案,於是把\(r\)輪搞成\(r\)次機會,所以想到這個狀態
Code
#include<stdio.h> #include<cstring> #include<cstdlib> #include<algorithm> #include<vector> #include<map> #include<set> #include<cmath> #include<iostream> #include<queue> #include<string> using namespace std; typedef long long ll; typedef pair<int,int> pii; typedef long double ld; typedef unsigned long long ull; typedef pair<long long,long long> pll; #define fi first #define se second #define pb push_back #define mp make_pair #define rep(i,j,k) for(register int i=(int)(j);i<=(int)(k);i++) #define rrep(i,j,k) for(register int i=(int)(j);i>=(int)(k);i--) ll read(){ ll x=0,f=1;char c=getchar(); while(c<‘0‘ || c>‘9‘){if(c==‘-‘)f=-1;c=getchar();} while(c>=‘0‘ && c<=‘9‘){x=x*10+c-‘0‘;c=getchar();} return x*f; } int T; int n,r,d[255]; double p[255]; double f[255][255],pw[255][255]; int main() { T=read(); while(T--) { n=read();r=read(); memset(f,0,sizeof(f)); for(int i=1;i<=n;i++) { scanf("%lf",&p[i]); d[i]=read(); } double ans=0; for(int i=1;i<=n;i++) { pw[i][0]=1; for(int j=1;j<=r;j++)pw[i][j]=pw[i][j-1]*(1-p[i]); } f[0][r]=1; for(int i=0;i<n;i++) for(int j=0;j<=r;j++) { f[i+1][j]+=f[i][j]*pw[i+1][j]; if(j-1>=0) { f[i+1][j-1]+=f[i][j]*(1-pw[i+1][j]); ans+=f[i][j]*(1-pw[i+1][j])*d[i+1]; } } printf("%.10lf\n",ans); } return 0; }
bzoj 4008 [HNOI2015] 亞瑟王