GYM101623E English Restaurant
Solution
好神啊,完全想不到 ╯︿╰
计算答案考虑期望的线性性,累加每张桌子的人数期望(取值*概率).
第i张桌子人数的取值受到一个限制:
假设第i张桌子的人光临时,第j-1张桌子还没有人坐,而[j,i)的桌子已经被占满,那么人数可能的取值范围就是[cj−1+1,ci].
所以第i张桌子的贡献就是每种[j,i)情况的概率然后乘上ci∑a=cj−1+1a.
考虑做两个dp辅助计算:
- fi,j : 占且仅占[i,j]的桌子的概率
- gi,j : [1,i)中占了j张桌子的概率
如果求出了f,g,则答案就是:
\begin{aligned}
ans=\sum\limits_{i=1}^n\sum\limits_{j=1}^i
(\frac{1}{G}\sum\limits_{a=c_{j-1}+1}^{c_i}a)
\cdot\sum\limits_{k=i-j+1}^t\binom{t}{k}(\frac{G-c_i}{G})^{t-k}
\cdot(\sum\limits_{l=i-j+1}^k\binom{l-1}{i-j}f_{j,i-1}g_{j-1,l-(i-j+1)}(\frac{c_i}{G})^{k-l})
\end{aligned}
k是枚举t个时刻中共有k个来的人数是\le c_i的.
l枚举的是加入第i张桌子后,[1,i]共坐了l张,即在第i张桌子被占之前,[1,i)的桌子中占了l-1张,也可以说是占第i张桌子的团体是k个\le c_i中的第l个.
最后>c_i的t-k个随便安排,\le c_i的k-l个在第i张桌子填上之后,所以也是随便安排.
把l这一维前缀和优化掉就是三方的.
现在考虑f,g怎么算.
f_{i,j}=\sum\limits_{k=i}^j \binom{j-i}{k-i}f_{i,k-1}f_{k+1,j}\frac{c_k-c_i-1}{G}
即枚举[i,j]中最后一个占的是第k张.
g_{i,j}=\sum\limits_{k=i-j}^i\binom{j}{i-k}f_{k,i-1}g_{k-1,j-(i-k)}
这个和计算答案的思想类似,枚举的k指第k-1张桌子还没有人坐,而[k,i)的桌子已经被占满.
感觉动态规划的精髓就在于怎样不重不漏地计算到所有情况和怎样把问题规模缩小啊,我大概一辈子也掌握不了精髓QAQ
Code
#include<bits/stdc++.h>
using namespace std;
#define REP(i,a,b) for(int i=(a),_ed=(b);i<=_ed;++i)
#define DREP(i,a,b) for(int i=(a),_ed=(b);i>=_ed;--i)
#define mp(x,y) make_pair((x),(y))
#define sz(x) (int)(x).size()
#define pb push_back
typedef long long ll;
typedef pair<int,int> pii;
inline int read(){
register int x=0,f=1;register char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=0;ch=getchar();}
while(isdigit(ch)){x=x*10+(ch^'0');ch=getchar();}
return f?x:-x;
}
const int N=1e2+5;
int n,G,t,c[N];
double C[N][N],f[N][N],g[N][N];
inline double power(double b,int n){double ans=1;for(;n;n>>=1,b*=b)if(n&1)ans*=b;return ans;}
inline int sum(int l,int r){return (l+r)*(r-l+1)/2;}
int main(){
//freopen("in.in","r",stdin);
REP(i,0,N-1)REP(j,C[i][0]=1,i)C[i][j]=C[i-1][j]+C[i-1][j-1];
n=read(),G=read(),t=read();
REP(i,1,n)c[i]=min(read(),G);
sort(c+1,c+n+1);
REP(i,1,n+1)f[i][i-1]=1;
REP(len,1,n)REP(i,1,n-len+1){
int j=i+len-1;
REP(k,i,j)f[i][j]+=C[j-i][k-i]*f[i][k-1]*f[k+1][j]*(c[k]-c[i-1])/G;
}
g[0][0]=1;
REP(i,1,n)REP(j,0,i-1)REP(k,i-j,i)
g[i][j]+=C[j][i-k]*f[k][i-1]*g[k-1][j-(i-k)];
double ans=0;
REP(i,1,n)REP(j,1,i){
double res=0;
REP(k,i-j+1,t){
res=res*c[i]/G+C[k-1][i-j]*g[j-1][(k-1)-(i-j)];
ans+=res*f[j][i-1]*C[t][t-k]*power(1.0*(G-c[i])/G,t-k)*sum(c[j-1]+1,c[i])/G;
}
}
printf("%.10f\n",ans);
return 0;
}
分类:
动态规划—普通dp
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
· 软件产品开发中常见的10个问题及处理方法
· 互联网不景气了那就玩玩嵌入式吧,用纯.NET开发并制作一个智能桌面机器人(四):结合BotSharp
· Vite CVE-2025-30208 安全漏洞
· MQ 如何保证数据一致性?
· 《HelloGitHub》第 108 期