#set page( paper: "a4", margin: (x: 2.5cm, y: 2.5cm), ) // 设置中文字体,根据你本地环境调整,通常推荐宋体或思源宋体 #set text( font: ("Noto Sans CJK SC", "Noto Serif CJK SC", "Noto Sans Mono CJK SC"), size: 11pt, lang: "zh" ) // 设置标题样式 #show heading: it => { set text(weight: "bold") block(above: 1.5em, below: 1em, it) } // 定义题目样式块 #let question_box(body) = { block( fill: luma(245), stroke: (left: 2pt + gray), inset: (x: 1em, y: 0.8em), radius: 4pt, width: 100%, text(style: "italic", body) ) } // 定义答案样式 #let solution(body) = { pad( left: 1em, top: 0.5em, bottom: 1em, text(fill: rgb("#000000"), body) ) } // 文档标题 #align(center)[ #text(size: 18pt, weight: "bold")[作业 3:约束满足问题 (CSP)] ] #line(length: 100%, stroke: 0.5pt + gray) = 一、约束满足问题:字母密码算术 #question_box[ 在字母密码算术问题中,已知 “SEND + MORE = MONEY”,每个字母代表 0-9 的唯一整数(首位字母 S、M 不能为 0)。其中 “SEND”“MORE”“MONEY” 分别表示由对应字母组成的四位数、四位数和五位数。请基于约束满足问题的框架解决该问题。 ] == 1. 变量集合 #question_box[ (2 分) 该问题的变量集合包含哪些元素?(需考虑加法运算中的进位) ] #solution[ 该问题的变量集合不仅包含出现的字母,还需包含各列加法产生的进位: - *字母变量*:$\{S, E, N, D, M, O, R, Y\}$ - *进位变量*:$\{C_1, C_2, C_3, C_4\}$ - $C_1$: 个位 $(D+E)$ 向十位的进位 - $C_2$: 十位 $(N+R)$ 向百位的进位 - $C_3$: 百位 $(E+O)$ 向千位的进位 - $C_4$: 千位 $(S+M)$ 向万位的进位 ] == 2. 关键约束条件 #question_box[ (2 分) 写出至少 3 条该问题的关键约束条件(例如变量取值范围约束、加法运算约束等) ] #solution[ 1. *全局互异约束 (AllDiff)*: $S, E, N, D, M, O, R, Y in \{0, dots, 9\}$ 且互不相同。 2. *首位非零约束*: $S != 0$ 且 $M != 0$。 3. *列加法约束(例如千位和万位)*: - 千位列:$S + M + C_3 = O + 10 times C_4$ - 万位列(最高位):$C_4 = M$ ] == 3. 启发式变量选择 #question_box[ (3 分) 若采用 “最少剩余值启发式” (MRV) 选择变量,在问题初始阶段(未赋值任何变量),应优先选择哪个变量进行赋值?请说明理由 ] #solution[ - *优先选择变量*:$M$ (或 $C_4$) - *理由*: MRV 策略要求选择当前合法取值最少的变量。两个四位数相加 ($"SEND" + "MORE"$) 最大结果不超 $19998$,因此结果 MONEY 的最高位 $M$ 只能取值 *1*。由于 $M$ 的定义域大小为 1 (最少),应最先被赋值。 ] == 4. 约束传播与更新 #question_box[ (3 分) 已知变量 M 的取值已确定为 1,此时需同步更新哪些变量的取值范围?请说明更新依据 ] #solution[ 需根据约束 $S + M + C_3 = O + 10 M$ 同步更新以下变量: 1. *更新 $O$ 的取值范围为 $\{0\}$*: 代入 $M=1$,得 $S + 1 + C_3 = O + 10$。因 $S <= 9, C_3 <= 1$,等式左边最大为 10,故右边必须为 10,解得 $O=0$。 2. *更新 $S$ 的取值范围为 $\{8, 9\}$*: 由上式简化得 $S + C_3 = 9$。若 $C_3=1 => S=8$;若 $C_3=0 => S=9$。 3. *更新 $C_4$ 的取值范围为 $\{1\}$*: 依据约束 $C_4 = M$。 ] #pagebreak() = 二、约束满足问题:医生排班 #question_box[ 某医院需安排甲、乙、丙、丁 4 名医生在周一至周五(共 5 天)进行值班,每人每周需值班 2 天,且每天至少有 1 名医生值班。额外要求: ① 甲不值班周一和周五; ② 乙的值班日需包含周三; ③ 丙的两天值班日不能相邻; ④ 任意两天的值班医生组成不能完全相同。 ] == 1. 变量与定义域 #question_box[ (2 分) 该问题的变量、定义域分别是什么? ] #solution[ 为了满足“每人值班2天”的结构,定义如下: - *变量*:$\{ "甲", "乙", "丙", "丁" \}$ - *定义域*:周一至周五($\{1, dots, 5\}$)中任选 2 天的所有组合。 - 初始定义域大小为 $C_5^2 = 10$ 种组合。 - 根据题目特定约束缩减后的初始域: - *甲*:$\{ \{2,3\}, \{2,4\}, \{3,4\} \}$ (排除含1, 5) - *乙*:$\{ \{1,3\}, \{2,3\}, \{3,4\}, \{3,5\} \}$ (必须含3) - *丙*:排除 $\{1,2\}, \{2,3\}$ 等相邻组合。 - *丁*:所有 10 种组合。 ] == 2. 约束条件形式化 #question_box[ (3 分) 用形式化语言描述该问题的所有约束条件(包括隐含约束) ] #solution[ 设 $V_i$ 为医生 $i$ 的值班日集合,$i in \{"甲", "乙", "丙", "丁"\}$。 1. *个人约束*: - $1 in.not V_"甲" and 5 in.not V_"甲"$ - $3 in V_"乙"$ - $forall d_1, d_2 in V_"丙", |d_1 - d_2| > 1$ 2. *覆盖约束*: - $union.big_i V_i = \{1, 2, 3, 4, 5\}$ 3. *每日医生组成唯一性约束*: - 设 $S_d = \{i | d in V_i\}$ 为第 $d$ 天值班的医生集合。 - $forall j, k in \{1..5\}, j != k => S_j != S_k$ ] == 3. 启发式变量选择 #question_box[ (2 分) 若采用 “最少剩余值启发式” 选择变量,在初始阶段应优先选择哪个变量?请说明理由 ] #solution[ - *优先选择变量*:*甲* - *理由*: 计算各变量满足自身硬性约束后的剩余合法组合数: - *甲*:排除周一、周五,仅剩 $\{ \{2,3\}, \{2,4\}, \{3,4\} \}$,共 *3* 个。 - *乙*:必须含周三,共 *4* 个。 - *丙*:排除相邻组合,共 *6* 个。 - *丁*:无限制,共 *10* 个。 甲的剩余合法值最少,故优先选择。 ] == 4. 约束传播与剪枝 #question_box[ (3 分) 若已知乙的值班日确定为周三和周四,此时需删除哪些变量的取值组合?请列举至少 3 组并说明依据 ] #solution[ 已知 $"乙" = \{3, 4\}$。为满足“任意两天医生组成不能完全相同 ($S_3 != S_4$)”的约束,需避免其他医生对 $S_3$ 和 $S_4$ 做出完全相同的贡献(即不能同时在3, 4号值班)。 需删除的取值组合: 1. *删除变量 甲 的取值 $\{3, 4\}$*。 依据:若甲选 $\{3,4\}$,且其他医生不区分这两天,会导致周三周四阵容雷同。 2. *删除变量 丁 的取值 $\{3, 4\}$*。 依据:同上,防止与乙的排班完全重叠。 3. *删除变量 丙 的取值 $\{3, 4\}$*。 依据:尽管丙因“不相邻”约束已不可选此值,但在域更新检查中,该组合因违反唯一性约束被显式标记为不可行。 ]