[jzoj 2941] 贿赂 {数学期望+dfs}

题目

议会里有N个议员,每个议员有两个属性:级别和忠诚值。
现在你要在议会通过一个议案,一个议案通过当且仅当严格超过一半的议员投赞同票。一个议员投赞同票的几率就是忠诚值除以100。
议员们有着奇怪的癖好:他们都喜欢吃糖。你带了K个糖果用来贿赂议员,每个糖果的作用是使得某个议员的忠诚值增加10。贿赂要在投票开始前完成。(注意任意议员的忠诚值不可能大于100)投票之后,如果议案没有通过,你就会很暴力地把投了反对票的所有议员暗杀掉。假设你要暗杀的议员集合是S,那么成功率就是A/(A+B);其中A是给定的常数,B是S中所有议员级别的和。当暗杀成功后你的议案就会获得通过。
现在要求最优贿赂方案下最大的成功几率是多大。

Input
第一行三个整数N,K和A,意义如题目所述;
接下来N行每行两个整数ai,bi分别表示每个议员的级别和忠诚值。

Output
一个实数表示可能的最大成功几率。保留6位小数。


解题思路

这种求数学期望的东西,一开始,我连样例都不知道怎么得到的。

赛后,作为难得AC了这道题目的WYC同学一个劲地重复一句话“为什么要看懂样例呢?”

没想到原来数据这么小,可以直接用暴力求出每个糖果的分配情况( d f s 函 数 dfs函数 dfs),然后在暴力求一下议会成功的概率( s o l v e 函 数 solve函数 solve)。
注意:类型转换的问题。


代码

#include
#include
#define ll long long 
#define N 10
#define rr register 
using namespace std;
ll a[N],b[N],f[N],n,k,con; double ans; 
inline double solve(ll x,ll y,ll z){
     //x是目前到那个人,y是有多少人同意,z是不同意的代价
	return (x>n)?(y>n/2?1.0:1.0*(con)/(con+z)):(f[x]/100.0*solve(x+1,y+1,z)+(100-f[x])/100.0*solve(x+1,y,z+a[x])); 
	//如果成功就返回1.0,没有成功就返回杀死反对票的概率。
	//概率为这个人同意的概率乘下一个人同意的概率+这个人不同意的概率乘下一个人不同意的概率
}
void dfs(ll x,ll y){
     //x是当前的位置,y是还剩下多少糖果
	if (x>n) {
     ans=max(ans,solve(1,0,0)); return;}
	for (rr int i=min((100-b[x])/10,y);i>=0;--i) 
	  f[x]=b[x]+i*10,dfs(x+1,y-i); 
}
int main()
{
     
	scanf("%lld%lld%lld",&n,&k,&con); 
	for (rr int i=1;i<=n;i++) scanf("%lld%lld",&a[i],&b[i]); dfs(1,k); 
	return 0&printf("%.6lf",ans); 
}


你可能感兴趣的:(数学期望,深度优先搜索(dfs),数学期望,dfs,jzoj,2941,贿赂)