**题目描述**
有 $n$ 份工作要分配给 $n$ 个人来完成,每个人完成一份。第 $i$ 个人完成第 $k$ 份工作所用的时间为一个正整数 $t_{i,k}$,其中 $1 \leq i, k \leq n$。试确定一个分配方案,使得完成这 $n$ 份工作的时间总和最小。
-
+
输入包含 $n + 1$ 行。
-
+
第 1 行为一个正整数 $n$。
-
+
第 2 行到第 $n + 1$ 行中每行都包含 $n$ 个正整数,形成了一个 $n \times n$ 的矩阵。在该矩阵中,第 $i$ 行第 $k$ 列元素 $t_{i,k}$ 表示第 $i$ 个人完成第 $k$ 件工作所要用的时间。
-
+
输出包含一个正整数,表示所有分配方案中最小的时间总和。
-
+
限制范围:
-
+
$1 \leq n \leq 15$
-
+
$1 \leq t_{i,k} \leq 10^4$
-
+
输入样例:
-
+
```text
5
9 2 9 1 9
8 8 1 8 4
9 1 7 8 9
```
-
+
输出样例:
-
+
```text
5
```
**分析**
-由于每个人都必须分配到工作,在这里可以建一个二维数组 `time[i][j]` ,用以表示 $i$ 个人完成 $j$ 号工作所花费的时间。给定一个循环,从第 1 个人开始循环分配工作,直到所有人都分配到。为第 $i$ 个人分配工作时,再循环检查每个工作是否已被分配,没有则分配给 $i$ 个人,否则检查下一个工作。可以用一个一维数组 `is_working[j]` 来表示第 $j$ 号工作是否已被分配,未分配则 `is_working[j]=0` ,否则 `is_working[j]=1` 。利用回溯思想,在工人循环结束后回到上一工人,取消此次分配的工作,而去分配下一工作直到可以分配为止。这样,一直回溯到第 1 个工人后,就能得到所有的可行解。在检查工作分配时,其实就是判断取得可行解时的二维数组的第一维下标各不相同和第二维下标各不相同。而我们是要得到完成这 $n$ 份工作的最小时间总和,即可行解中和最小的一个,故需要再定义一个全局变量 `cost_time_total_min` 表示最终的时间总和,初始 `cost_time_total_min` 为 `time[i][i]` 之和,即对角线工作时间相加之和。在所有人分配完工作时,比较 $count$ 与 `cost_time_total_min` 的大小,如果 $count$ 小于 `cost_time_total_min` ,证明在回溯时找到了一个最优解,此时就把 $count$ 赋给 `cost_time_total_min` 。但考虑到算法的复杂度,这里还有一个剪枝优化的工作可以做。就是在每次计算局部费用变量 $count$ 的值时,如果判断 $count$ 已经大于 `cost_time_total_min` ,就没必要再往下分配了,因为这时得到的解必然不是最优解。
+由于每个人都必须分配到工作,在这里可以建一个二维数组 `time[i][j]` ,用以表示 $i$ 个人完成 $j$ 号工作所花费的时间。给定一个循环,从第 1 个人开始循环分配工作,直到所有人都分配到。为第 $i$ 个人分配工作时,再循环检查每个工作是否已被分配,没有则分配给 $i$ 个人,否则检查下一个工作。可以用一个一维数组 `is_working[j]` 来表示第 $j$ 号工作是否已被分配,未分配则 `is_working[j]=0` ,否则 `is_working[j]=1` 。利用回溯思想,在工人循环结束后回到上一工人,取消此次分配的工作,而去分配下一工作直到可以分配为止。这样,一直回溯到第 1 个工人后,就能得到所有的可行解。
+
+在检查工作分配时,其实就是判断取得可行解时的二维数组的第一维下标各不相同和第二维下标各不相同。而我们是要得到完成这 $n$ 份工作的最小时间总和,即可行解中和最小的一个,故需要再定义一个全局变量 `cost_time_total_min` 表示最终的时间总和,初始 `cost_time_total_min` 为 `time[i][i]` 之和,即对角线工作时间相加之和。在所有人分配完工作时,比较 $count$ 与 `cost_time_total_min` 的大小,如果 $count$ 小于 `cost_time_total_min` ,证明在回溯时找到了一个最优解,此时就把 $count$ 赋给 `cost_time_total_min` 。
+
+但考虑到算法的复杂度,这里还有一个剪枝优化的工作可以做。就是在每次计算局部费用变量 $count$ 的值时,如果判断 $count$ 已经大于 `cost_time_total_min` ,就没必要再往下分配了,因为这时得到的解必然不是最优解。
#### 经典例题代码
}
}
int main(int argc, char const *argv[]) {
- setvbuf(stdin, new char[1 << 20], _IOFBF, 1 << 20);
- setvbuf(stdout, new char[1 << 20], _IOFBF, 1 << 20);
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {