【区间DP+期望】Gym101623E English Restaurant

【题目】
原题地址
一个餐厅有 n n n张桌子,第 i i i张座位数为 c i c_i ci。先后有 t t t群人来吃饭,人数为 [ 1 , g ] [1,g] [1,g]中随机一个数。他们会找一张恰好能坐下的桌子坐下(找不到就离开)。求最终期望有多少个人吃饭。 n , t ≤ 100 , g , c i ≤ 200 n,t\leq 100,g,c_i\leq 200 n,t100,g,ci200

【解题思路】
首先我们可以先添加 n n n个座位 + ∞ +\infty +的桌子表示离开餐馆,然后按座位数排序。

考虑用期望的定义来求答案,同时 DP \text{DP} DP出总和和方案数。

注意到最后占据的一定是若干个区间,每个区间可以独立计算。

我们设 f i , j f_{i,j} fi,j表示只有 [ i , j ] [i,j] [i,j]的桌子被占据的人数总和以及方案数,枚举最后一张坐的桌子是什么来进行转移,这里有一个组合数 ( j − i k − i ) {j-i\choose k-i} (kiji)表示前 j − i j-i ji张桌子的排列种类数。

然后设 g i , j g_{i,j} gi,j表示 [ i , t ] [i,t] [i,t]这些人占据了 [ j , n ] [j,n] [j,n]这些桌子的总和以及方案数,利用前缀和优化转移。

(或者我们可以设接下来设 g i , j g_{i,j} gi,j表示前 i i i张桌子占了 j j j张的期望。枚举 k k k表示 i − k + 1 ∼ i i-k+1\sim i ik+1i都占了, i − k i-k ik不占,当 k = 0 k=0 k=0表示 i i i不占,这里有一个组合数 ( j k ) {j\choose k} (kj)表示前 j j j张桌子顺序。)

复杂度 O ( n 3 ) O(n^3) O(n3)

【参考代码】

#include<bits/stdc++.h>
#define pb push_back
#define mkp make_pair
#define fi first
#define se second
using namespace std;

typedef double db;
typedef long long ll;
typedef pair<db,db> pdd;
const int N=205;
int n,g,t,c[N];
db C[N][N];
pdd w[N][N],f[N][N],s[N][N];

int read()
{
	int ret=0,f=1;char c=getchar();
	while(!isdigit(c)) {if(c=='-')f=0;c=getchar();}
	while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
	return f?ret:-ret;
}
pdd operator +(const pdd&a,const pdd&b){return mkp(a.fi*b.se+a.se*b.fi,a.se*b.se);}
pdd operator *(const pdd&a,const pdd&b){return mkp(a.fi+b.fi,a.se+b.se);}

void initC()
{
	for(int i=0;i<N;++i)
	{
		C[i][i]=C[i][0]=1;
		for(int j=1;j<i;++j) C[i][j]=C[i-1][j]+C[i-1][j-1];
	}
}

pdd calc(int l,int r)
{
	int x=min(g,l>0?c[l-1]:0),y=min(g,c[r]);
	return mkp(c[r]<N?(y*(y+1)-x*(x+1))/2:0,y-x);
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("E.in","r",stdin);
	freopen("E.out","w",stdout);
#endif
	initC();n=read();g=read();t=read();
	for(int i=0;i<n;++i) c[i]=read();
	for(int i=0;i<t;++i) c[n++]=N;
	sort(c,c+n);
	for(int i=0;i<n;++i)
	{
		w[i][i]=calc(i,i);
		for(int j=i-1;~j;--j) for(int k=j;k<=i;++k)
		{
			pdd tmp=mkp(0,C[i-j][k-j])+calc(j,k);
			if(j<k) tmp=tmp+w[j][k-1];
			if(i>k) tmp=tmp+w[k+1][i];
			w[j][i]=w[j][i]*tmp;
		}
	}
	for(int i=t-1;~i;--i) for(int j=n-1;~j;--j) f[i][j]=w[j][j+t-i-1];
	for(int i=t-1;~i;--i) for(int j=n-1;~j;--j) 
	{
		for(int k=i+1;k<t;++k) 
			f[i][j]=f[i][j]*(mkp(0,C[t-i][t-k])+w[j][j+k-i-1]+s[k][j+k-i+1]);
		s[i][j]=s[i][j+1]*f[i][j];
	}
	pdd ans=mkp(0,0);
	for(int i=0;i<n;++i) ans=ans*f[0][i];
	printf("%.10lf\n",ans.fi/ans.se);
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PyCharm是一个集成开发环境(IDE),用于Python编程语言的开发。它提供了许多功能,例如代码编辑、调试和版本控制等。Gym是一个用于开发和比较强化学习算法的开源Python库。它提供了许多预定义的环境,供开发者进行强化学习实验。在安装深度强化学习环境的教程中,引用提到了在Windows 10上安装Anaconda、PyTorch、PyCharm和Gym等软件和包。引用提到了需要下载的软件和包,包括Anaconda、Pycharm、Python、PyTorch、Gym以及Pygame等。而引用中提到了通过pip命令来安装Gym库。综上所述,PyCharm和Gym都是用于Python开发和深度强化学习的工具和库。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [DRL环境安装:Win10+Anaconda+PyTorch+PyCharm+Gym](https://blog.csdn.net/weixin_42480812/article/details/112054592)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [Anaconda+PyCharm+PyTorch+Gym深度强化学习环境搭建 送新手直接送进炼丹炉](https://blog.csdn.net/qq_43674552/article/details/127343863)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值