ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CF1267G-Game Relics【数学期望,dp】

2022-01-24 22:34:58  阅读:147  来源: 互联网

标签:leq int sum 花费 CF1267G Game Relics 物品 roll


正题

题目链接:https://www.luogu.com.cn/problem/CF1267G


题目大意

给出\(n\)个物品,你可以进行如下操作

  • 花费\(x\)获得随机一个物品。
  • 花费\(c_i\)获得第\(i\)个物品。

\(1\leq n\leq 100,1\leq x\leq 10000,\sum a_i\leq 10^4\)


解题思路

一个显然的策略是我们先roll完再买,所以我们可以分开考虑两部分先。

首先假设我们roll到了\(x\)个物品,显然所有大小为\(x\)的物品集合都是等概率出现的。而至于roll出\(x\)个物品的期望花费我们也很好算。

但是我们显然很难从一种情况下的下一步方案考虑,因为能到达每个方案的期望都是不同的,而我们不可能记录所有方案。

但是有一个很巧妙的方法,我们花钱也可以视为随意\(roll\)物品,假设目前没有获得的物品费用和为\(s\),个数为\(k\),那么我们就可以视为花费\(\frac{s}{k}\)的期望随机\(roll\)出一个物品。

此时两种方案造成的结果都是多一个随机未获得物品,但是花费不同,我们直接取\(min\)即可。

那么现在的做法已经很显然了,设\(f_{i,j}\)表示\(i\)个物品的集合中花费和为\(j\)的概率,然后考虑两种方案的哪个更优就好了。

时间复杂度:\(O(n\sum a_i)\)


code

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,sum;
double ans,x,f[110][110000];
int main()
{
	scanf("%d%lf",&n,&x);x/=2.0;
	f[0][0]=1;
	for(int i=1,a;i<=n;i++){
		scanf("%d",&a);sum+=a;
		for(int j=i;j>=1;j--)
			for(int k=sum;k>=a;k--)
				f[j][k]+=f[j-1][k-a]*j/double(n-j+1);
	}
	for(int i=1;i<=n;i++)
		for(int j=0;j<=sum;j++)
			if(f[i][j]!=0.0)
				ans=(ans+f[i][j]*min(((double)n/i+1.0)*x,(double)j/i));
	printf("%.12lf\n",ans);
	return 0;
}

标签:leq,int,sum,花费,CF1267G,Game,Relics,物品,roll
来源: https://www.cnblogs.com/QuantAsk/p/15841139.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有