You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

模拟Secretary problem(秘书问题)结果异常,期望37%却仅得约10%

秘书问题模拟错误分析与修正

核心错误:统计目标完全偏离秘书问题定义

秘书问题的核心是计算选中全局最优候选人(即分数最大值)的概率,但你的代码一直在累加选中者的分数平均值——这完全是两个不同的指标。你现在找的是“能拿到最高平均分数”的策略,而非“选中最优者概率最高”的策略,这就是结果和1/e(约37%)完全不匹配的根本原因。

代码中的具体问题

  • 统计逻辑完全错误:你应该统计「每次试验中,当前策略是否选中了全局最大值」,而非累加选中者的分数。比如每次试验先记录全局最大值,再判断按策略选中的是否为该值,是则计数+1,最终用计数/试验次数得到该策略的成功率。
  • 变量命名误导:let min=Math.max(...x.splice(0,i));里的min完全是错误命名,应该叫maxRejected或bestInFirstI,虽然不影响运行,但会干扰问题排查。
  • select!=0判断有漏洞:如果前i个的最大值是0.8,剩下的候选人分数都低于0.8,select会保持0,此时你加的是最后一个人的分数,但这种情况策略根本没选中全局最大值,你的统计方式完全没记录这个关键信息。

修正后的代码

// 候选人数量
const people = 100;
// 试验次数,建议增加到10000以获得更稳定的结果
const trials = 10000;

// 记录每个策略(拒绝前i个)选中最优者的次数
const successCounts = new Array(people).fill(0);

for (let i = 0; i < people; i++) {
    for (let j = 0; j < trials; j++) {
        // 生成随机分数数组,每个候选人分数为0-1的独立随机数
        const scores = Array.from({ length: people }, () => Math.random());
        // 获取全局最大值
        const globalMax = Math.max(...scores);
        // 计算前i个候选人中的最高分
        let maxRejected = -Infinity;
        if (i > 0) {
            maxRejected = Math.max(...scores.slice(0, i));
        }
        // 执行策略:从第i+1个开始,选第一个比maxRejected高的候选人
        let selectedScore = null;
        for (let k = i; k < people; k++) {
            if (scores[k] >= maxRejected) {
                selectedScore = scores[k];
                break;
            }
        }
        // 若后续无人达标,选最后一个候选人
        if (selectedScore === null) {
            selectedScore = scores[people - 1];
        }
        // 判断是否选中全局最大值,是则计数+1
        if (selectedScore === globalMax) {
            successCounts[i]++;
        }
    }
}

// 计算每个策略的成功率
const successRates = successCounts.map(count => count / trials);
// 找到成功率最高的策略对应的拒绝比例
const bestIndex = successRates.indexOf(Math.max(...successRates));
const bestPercentage = (bestIndex / people * 100).toFixed(2);
console.log(`最优策略:拒绝前 ${bestPercentage}% 的候选人,成功率约 ${(Math.max(...successRates)*100).toFixed(2)}%`);

额外说明

你怀疑的let x=new Array(people).fill(0).map(e=>Math.random())这行代码是没问题的:fill(0)后用map生成每个独立的随机数,每个元素都是不同的随机值,完全符合模拟需求。

内容的提问来源于stack exchange,提问作者Anonymous Camel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 10:05:23