HDU 1203 I NEED A OFFER!(考虑状态的对立面)

题目描述

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(0n10000,0m10000)
后面的 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.90.8
申请学校 1 1 1 3 3 3:没收到offer的概率为 0.9 ∗ 0.7 0.9*0.7 0.90.7
申请学校 2 2 2 3 3 3:没收到offer的概率为 0.8 ∗ 0.7 0.8*0.7 0.80.7

6 6 6 个数据中,没收到offer的最小概率为 0.8 ∗ 0.7 0.8*0.7 0.80.7,所以至少收到一份offer的最大概率为 44 % 44\% 44%

定义 d p [ i ] dp[i] dp[i]:表示的是在预算为 i i i ,至少得到一份offer的最大概率。

1 − b [ i ] 1-b[i] 1b[i] :选这个学校没录的概率。
d p [ j − a [ i ] ] dp[j-a[i]] dp[ja[i]]:选学校 i i i 之前,录取的概率。
1 − d p [ j − a [ i ] ] 1-dp[j-a[i]] 1dp[ja[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;
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zaiyang遇见

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值