【完全背包】HDU-1203 I NEED A OFFER!

在这里插入图片描述

注解

1、此题是0/1背包,或者叫完全背包,每个物品最多只有1个,选或不选,在给定容量前提下,使得收益最大。
2、将输入的学校和概率分别用两个数组存储(也可以用一个结构体)。要计算至少得到一份offer的最大概率,反面算,就是用1减去一个offer都没有的最小概率。一个offer都没有,就是每个offer都没获得的概率的连乘。因此初始化的时候就用prob[i] = 1.0 - prob[i];,数组内存储的就是未获得该offer的概率。
3、背包求最优解,从前往后计算或者从后往前计算应该都是可行的,但是要注意不要暴力循环!本题的做法是m所学校,因此第一重循环是0到m,第二层循环初始值是n,也就是拥有的最大费用,循环条件的终止点是第i个学校的费用(只有当前费用>=第i所学校的费用时,才能申请该学校啊),循环体内就一句话,这个学校选还是不选,求概率的最小值。

//m个offer 
for(int i=0; i<m; i++) {
    	//从后往前依次计算最小值 
    	for(int j=n; j>=pos[i]; j--) {
    		//选和不选,两种情况,取最小值 
    		minProb[j] = min(minProb[j], minProb[j-pos[i]]*prob[i]);
    	}
 }

4、计算的是未被录取的概率,输出要取反。另外要输出百分比(注意百分号如何输出),且保留一位小数。

代码

#include <iostream>

using namespace std;

int main() {

	int n, m;
	scanf("%d %d", &n, &m);
	while(n || m) {
		int pos[m];
		double prob[m];
		for(int i=0; i<m; i++) {
			scanf("%d %lf", &pos[i], &prob[i]);
			//反面考虑:至少有一个offer的反面就是一个offer都没有 
			prob[i] = 1.0 - prob[i];
		}

		double minProb[n+1];
		for(int i=0; i<n+1; i++) {
			minProb[i] = 1.0;
		}
		//m个offer 
		for(int i=0; i<m; i++) {
			//从后往前依次计算最小值 
			for(int j=n; j>=pos[i]; j--) {
				//选和不选,两种情况,取最小值 
				minProb[j] = min(minProb[j], minProb[j-pos[i]]*prob[i]);
			}
		}
		printf("%.1lf%%\n", 100.0 * (1.0-minProb[n]);
		scanf("%d %d", &n, &m);
	}

	return 0;
}

结果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值