题目如下
新冠疫情由新冠病毒引起,最近在 A 国蔓延,为了尽快控制疫情,A 国准 备给大量民众进病毒核酸检测。
然而,用于检测的试剂盒紧缺。为了解决这一困难,科学家想了一个办法:合并检测。即将从多个人(k 个)采集的标本放到同一个试剂盒中进行检测。如果结果为阴性,则说明这 k 个人都是阴性,用一个试剂盒完成了 k 个人的检测。如果结果为阳性,则说明 至少有一个人为阳性,需要将这 k 个人的样本全部重新独立检测(从理论上看, 如果检测前 k−1 个人都是阴性可以推断出第 k 个人是阳性,但是在实际操作中 不会利用此推断,而是将 k 个人独立检测),加上最开始的合并检测,一共使用 了 k + 1 个试剂盒完成了 k 个人的检测。
A 国估计被测的民众的感染率大概是 1%,呈均匀分布。请问 k 取多少能最节省试
剂盒?
以下程序实现了这一功能,请你补全以下空白处内容:
#include <stdio.h>
int main()
{
double m = 4537;
double min = 9999999;
double k, sum, ans;
for (k = 1; k <= 100; k++)
{
sum = (m - k) / k + 0.01 * m * k + 1;
__________________;
}
printf("%d\n", (int)ans);
return 0;
}
提示:
设检测人数为100人,根据概率为1%,则只有1个为阳性。k个人一组,则需要的试剂数量
为:对所有分组进行合并检测所需要的试剂数100/k+其中1个分组阳性所需要的试剂数k+
未分组人数所需的试剂数量。
其实题中已经给出了部分代码,不过博主个人认为这个解题思路有点理解不了,很难让人明白为什么要这么做,有兴趣的同学可以顺着这个思路想下去,欢迎评论区讨论。
今天博主的思考方式略微有些不同,咱们先看看代码,然后根据代码,一步步给大家解析思路,最终达到理解的程度:
#include <bits/stdc++.h>
using namespace std;
int main()
{
/*
检测总人数,我们假定一个值,也可以设置的更大,但其实没这个必要,想改值的也
可以试试,结果不出意外应该都一样
*/
double m = 4537;
/*
每组人数最小值,这里设置一个绝对大的值,但肯定用不上,一组绝对不会这么多人,
作用是方便我们做比较的时候设置最小值
*/
double min = 99999;
/*
这里的三个值是我们需要用到来计算的,不得不叹息一声,数学才是万能的啊
k:每次合并检测的人数
sum:所需试剂盒数
ans:最优k的解
*/
double k, sum, ans;
/*
循环,直至找到最优解,k设置100是因为一组绝对不会100人,代价太大,我们
现实中检测也不过就是10人一组,因为一旦有一个人感染,那么必须一个人一个
试剂盒,绝对的浪费
*/
for (k = 1;k < 100;k++)
{
/*
这里是总人数整除每组人数取余,如果刚好除尽,这么多人首次检测就只需
要m/k个试剂盒
*/
if ((int)m % (int)k == 0)
{
/*
m/k是首次检测这么多人需要的试剂盒,0.01*m是出现感染人的数量,
因为感染人是平均分布的,所以可以认为有0.01*m的分组中,每组存
在一个感染者,需要对这些组的每一个人进行单独的检测,每组人数为k,
则二次检测需要0.01*m*k个检测盒,加起来就是一共的检测数
*/
sum = m / k + 0.01 * m * k;
}
else
{
/*
这里和上面是一样的道理,因为除不尽,所以需要额外增加一个检测盒,
不过这里有个特殊情况,如果被感染者刚好存在于最后这个不足k人的
分组中,这一组总检测试剂盒数是不足k的,但是这种情况被忽略了,
原因是,即使不足k人,差距也不过就是几个,跟全体比起来微不足道,
这样的分组一般也存在极少数,所以这种极低概率事件在这种大数量检
测情况下可以忽略不计。(同学们切不可钻牛角尖,“大局为重”)
*/
sum = m / k + 0.01 * m * k + 1;
}
//看这里,min派上用场了
if (sum < min)
{
//min=sum,所以每一次都取到的是sum(总试剂盒)的最小值
min = sum;
//最小值对应的k就是最佳每组人数
ans = k;
}
}
/*
最后输出最佳人数,为10,果然和我们现实中检测是一样的,厉害了,再次感叹,
算法来源于数学,数学牛逼
*/
cout << ans << endl;
return 0;
}
注释写的非常清楚了同学们,仔细看就一定能理解这个算法,个人认为要比原题目中那种思路要容易理解的多。
最后,有什么不理解的欢迎评论区留言讨论!