题解
- 题目大意:每个人有两个值a[i],b[i]为各自的等级和忠诚值,现在有k颗糖果分配出去(一个人可以拿多颗),每颗可以使一个人的忠诚值+10,若得到票数的概率没有超过一半,那么要暗杀,暗杀成功的概率为A/(A+B),其中B是所有人的等级和,问成功的概率
- 首先,这个数据范围十分感人
- 考虑直接dfs来枚举分配糖果的方案,这样的时间复杂度是O(n!)的
- 那么对于n个人的忠诚值,如何求他成功的概率
- 考虑可以递归来做,每个人就有两种情况,一种是选,就乘上选的概率,一种是不选,那就乘上不选的概率
- 如果递归到最后的一种情况中,所得票数没有超过半数,那么就要乘上暗杀成功的概率
- 最后所有概率取一个最大值就好了
代码
1 #include <cstdio>
2 #include <iostream>
3 #include <cstring>
4 #define N 10
5 using namespace std;
6 int n,k,A,a[N],b[N];
7 double ans;
8 double work(int x,int y,int B)
9 {
10 if (x>n) { if (y*2>n) return 1.0; else return 1.0*A/(A+B); }
11 return 1.0*b[x]/100*work(x+1,y+1,B)+1.0*(1-1.0*b[x]/100)*work(x+1,y,B+a[x]);
12 }
13 void dfs(int x,int y)
14 {
15 if (x==n)
16 {
17 if (y!=0) b[x]+=y*10;
18 if (b[x]<=100) ans=max(ans,work(1,0,0));
19 b[x]-=y*10; return;
20 }
21 for (int i=0;i<=y;i++)
22 {
23 b[x]+=i*10;
24 if (b[x]<=100) dfs(x+1,y-i); else { b[x]-=i*10; break; }
25 b[x]-=i*10;
26 }
27 }
28 int main()
29 {
30 scanf("%d%d%d",&n,&k,&A);
31 for (int i=1;i<=n;i++) scanf("%d%d",&a[i],&b[i]);
32 dfs(1,k),printf("%.6lf",ans);
33 }