题目描述
Speakless很早就想出国,现在他已经考完了所有需要的考试,准备了所有要准备的材料,于是,便需要去申请学校了。要申请国外的任何大学,你都要交纳一定的申请费用,这可是很惊人的。
Speakless没有多少钱,总共只攒了
n
n
n 万美元。他将在
m
m
m 个学校中选择若干的(当然要在他的经济承受范围内)。每个学校都有不同的申请费用
a
a
a(万美元),并且Speakless估计了他得到这个学校offer的可能性
b
b
b。不同学校之间是否得到offer不会互相影响。
“I NEED A OFFER”,他大叫一声。帮帮这个可怜的人吧,帮助他计算一下,他可以收到至少一份 offer 的最大概率。(如果Speakless选择了多个学校,得到任意一个学校的offer都可以)。
输入格式
输入有若干组数据,每组数据的第一行有两个正整数
n
,
m
(
0
≤
n
≤
10000
,
0
≤
m
≤
10000
)
n,m(0\leq n \leq 10000,0 \leq m \leq 10000)
n,m(0≤n≤10000,0≤m≤10000)。
后面的
m
m
m 行,每行都有两个数据
a
i
a_i
ai (整型),
b
i
b_i
bi (实型)分别表示第
i
i
i 个学校的申请费用和可能拿到 offer 的概率。
输入的最后有两个
0
0
0。
输出格式
每组数据都对应一个输出,表示Speakless可能得到至少一份offer的最大概率。用百分数表示,精确到小数点后一位。
输入样例
10 3
4 0.1
4 0.2
5 0.3
0 0
输出样例
44.0%
提示
你应该使用 printf(“%%”) 去输出 a ‘%’.
提交链接
https://acm.hdu.edu.cn/showproblem.php?pid=1203
解析
至少收到一份offer的最大概率 = 1 - 一份都没收到的最小概率。
就拿样例来说:
有
10
10
10 万元,可以拿来申请一个学校。
申请学校
1
1
1,没收到offer的概率为
0.9
0.9
0.9
申请学校
2
2
2,没收到offer的概率为
0.8
0.8
0.8
申请学校
3
3
3,没收到offer的概率为
0.7
0.7
0.7
也可以拿来申请两个学校
申请学校
1
1
1 和
2
2
2:没收到offer的概率为
0.9
∗
0.8
0.9*0.8
0.9∗0.8
申请学校
1
1
1 和
3
3
3:没收到offer的概率为
0.9
∗
0.7
0.9*0.7
0.9∗0.7
申请学校
2
2
2 和
3
3
3:没收到offer的概率为
0.8
∗
0.7
0.8*0.7
0.8∗0.7
6 6 6 个数据中,没收到offer的最小概率为 0.8 ∗ 0.7 0.8*0.7 0.8∗0.7,所以至少收到一份offer的最大概率为 44 % 44\% 44%。
定义 d p [ i ] dp[i] dp[i]:表示的是在预算为 i i i ,至少得到一份offer的最大概率。
1
−
b
[
i
]
1-b[i]
1−b[i] :选这个学校没录的概率。
d
p
[
j
−
a
[
i
]
]
dp[j-a[i]]
dp[j−a[i]]:选学校
i
i
i 之前,录取的概率。
1
−
d
p
[
j
−
a
[
i
]
]
1-dp[j-a[i]]
1−dp[j−a[i]]: 选学校
i
i
i 之前,没录取的概率。
参考代码
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=1e4+9;
int n,m,a[maxn];
double b[maxn],dp[maxn]; //dp[i]:预算为i,得到一份offer的最大概率
int main()
{
while(cin>>n>>m) //预算为n元 m个学校
{
if(n+m==0)
break;
memset(dp,0,sizeof(dp));
for(int i=1; i<=m; i++)
cin>>a[i]>>b[i]; //申请第i个学校的费用 和通过的概率
for(int i=1; i<=m; i++)
{
for(int j=n; j>=a[i]; j--) //类似01背包
{
dp[j]=max(dp[j],1-(1-dp[j-a[i]])*(1-b[i]));
}
}
printf("%.1f%%\n",dp[n]*100);
}
return 0;
}