图 1:本文封面,从第一次点数到最优策略的决策流程。
先说明属性:这是一篇笔试真题复盘,题目出自本地历史面试资料整理,与任何公司的当前招聘无关。题面很短:扔一个骰子,扔到几点就返现几元;第一次扔完看到点数后,你可以二选一——直接拿走这个点数,或者再扔一次,但这时只能拿第二次的点数。玩一轮的期望收益是多少?选项里躺着 3.5、4、4.25 好几个干扰项。
一句话结论:最优策略是「第一次扔到 4、5、6 就收下,扔到 1、2、3 就重扔」,期望收益 4.25 元。
解这道题只有一个关键动作:先给「重扔」标个价。
很多人卡住是因为把两次投掷搅在一起算。换个顺序:先问自己,「再扔一次」这个权利值多少钱?第二次投掷是一次普通投掷,期望就是六个点数的平均值:
E = (1+2+3+4+5+6) ÷ 6 = 3.5
于是第一次的决策变成一道比价题:手里的点数和 3.5 比,谁大要谁。扔到 4、5、6,收下更划算;扔到 1、2、3,不如换成期望 3.5 的重扔机会。注意 3.5 不在骰子的任何一面上,所以不存在拿不准的边界——阈值天然落在 3 和 4 之间。这就是阈值策略:最优策略只需要一个分界线,不用记任何额外状态。
这里有一个容易被忽略的约束在悄悄起作用:规则规定重扔之后必须接受第二次结果,没有第三次机会。正因为「反悔权」只有一层,「重扔」的价值才能用一个固定的 3.5 封死;如果可以无限重扔直到满意,期望值会一路逼近 6 元,题目也就成了另一道题。所以答题时先把约束念清楚——重扔只有一次、结果必须接受——再开始算,既避免自己跑偏,也让面试官看到你的前提意识。
算总账:按第一次的六种结果分段求期望。
第一次扔到 4、5、6 的概率各 1/6,收益就是点数本身;扔到 1、2、3 的概率合计 3/6,收益换成重扔的期望 3.5:
E* = 1/6×(4+5+6) + 3/6×3.5 = 2.5 + 1.75 = 4.25
干扰项 3.5 是「只有一次投掷」的期望——把重扔权利白白扔掉的价格;两个数一减,重扔这个选择权本身价值 0.75 元,这正是这道题真正想考的东西:期权的价值来自「坏结果可以重抽」。
解析解之外,用蒙特卡洛模拟把所有阈值扫一遍验证(Node.js 22.15.0,node dice.js):
const roll = () => 1 + Math.floor(Math.random() * 6);
function play(threshold) { // 第一次 < threshold 就重扔
const first = roll();
return first >= threshold ? first : roll();
}
for (const t of [2, 3, 4, 5, 6, 7]) {
let sum = 0;
for (let i = 0; i < 1000000; i++) sum += play(t);
console.log(`阈值 ${t}(<${t} 重扔): 模拟期望 ${(sum / 1000000).toFixed(4)}`);
}
const exact = (4 + 5 + 6) / 6 + (3 / 6) * 3.5;
console.log(`解析解 E* = ${exact}`);
实测输出:
阈值 2(<2 重扔): 模拟期望 3.9181
阈值 3(<3 重扔): 模拟期望 4.1662
阈值 4(<4 重扔): 模拟期望 4.2488
阈值 5(<5 重扔): 模拟期望 4.1680
阈值 6(<6 重扔): 模拟期望 3.9172
阈值 7(<7 重扔): 模拟期望 3.4989
解析解 E* = 4.25
一百万次模拟下阈值 4 跑出 4.2488,与解析解 4.25 吻合,而且整排阈值里只有它登顶——阈值抬高到 5,等于把「4」这种该收的结果也拿去赌,期望立刻掉回 4.17。模拟不仅验证答案,还验证了「阈值策略里最优的就是 4」这个更强的结论。
图 2:基准线、阈值决策表与期望汇总公式。
面试现场的答题结构与失分点。
先把「重扔值 3.5」这个基准线立起来,再讲阈值的由来,最后分段求和收尾,三分钟讲完。失分点有三个:一是直接答 3.5,把重扔权利当成白送的;二是把两次取平均,误以为收益是两次点数的均值——规则是只能拿一次;三是阈值定错,把 3 也算进「收下」。如果追问「能重扔两次呢」,思路不变,从后往前推:先算最后一扔值 3.5,再算倒数第二扔的阈值,每多一次机会基准线就抬高一次,这就是动态规划里的倒推法。你被问过类似的期望决策题吗?当时是倒推出来的还是正面硬算的?欢迎分享。