BSOJ8163题解
看到值域很小而且时限 4s 以为是什么高明的依赖值域的复杂度,结果就是优化 DP。
考场上只想到了 \(O(n^5)\) 的还是太菜了。
设 \(dp[l][r][x]\) 表示 \([l,r]\) 这个区间中 \(x\) 赢得最终胜利的概率。容易有 \(O(n^5)\) 转移。
但是很显然 \(x\) 左边的人不可能与右边的人对战,所以 \([l,x]\) 和 \([x,r]\) 这两个区间是完全独立的。
也就是说 \(dp[l][r][x]=F[l][x]\times G[x][r]\),\(F[l][r]\) 表示 \([l,r]\) 这个区间中 \(r\) 取得了最终的胜利,\(G[l][r]\) 定义相反。
转移:
\[F[l][r]=\frac{1}{r-l}\sum_{k=l}^{r-1}\sum_{x=l}^{k}F[l][x]\times G[x][k]\times\frac{a_r}{a_x+a_r}\times F[k+1][r]
\]
\(G\) 类似。
设 \(f[l][r]=\sum_{i=l}^{r}G[l][i]\times F[i+1][r]\),那么有:
\[F[l][r]=\frac{1}{r-l}\sum_{x=l}^{r-1}F[l][x]\times f[x][r]\times\frac{a_r}{a_x+a_r}
\]
没了。复杂度 \(O(n^3)\)。注意边界。
#include<cstdio>
#include<cctype>
namespace SOLVE{
typedef double db;
const int M=505;
int n,k,a[M];db F[M][M],G[M][M],H[M][M];
inline void main(){
scanf("%d%d",&n,&k);for(int i=1;i<=n;++i)scanf("%d",a+i),F[i][i]=G[i][i]=1;
for(int t=2;t<=n;++t){
for(int l=1,r=t;r<=n;++l,++r){
for(int i=l;i<r;++i)H[l][r]+=G[l][i]*F[i+1][r];
for(int i=l;i<r;++i)F[l][r]+=1.*a[r]/(a[i]+a[r])*F[l][i]*H[i][r];
for(int i=r;i>l;--i)G[l][r]+=1.*a[l]/(a[i]+a[l])*H[l][i]*G[i][r];
F[l][r]/=r-l;G[l][r]/=r-l;
}
}
printf("%.10lf",F[1][k]*G[k][n]);
}
}
signed main(){
SOLVE::main();
}