#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\}$*。
     依据：尽管丙因“不相邻”约束已不可选此值，但在域更新检查中，该组合因违反唯一性约束被显式标记为不可行。
]
