A few bug fixes.

pull/918/head
krahets 1 year ago
parent 6c16276494
commit 5f3ad1ed3d

@ -26,7 +26,7 @@ int coinChangeDP(int coins[], int amt, int coinsSize) {
for (int i = 1; i <= n; i++) {
for (int a = 1; a <= amt; a++) {
if (coins[i - 1] > a) {
// 若超过背包容量,则不选硬币 i
// 若超过目标金额,则不选硬币 i
dp[i][a] = dp[i - 1][a];
} else {
// 不选和选硬币 i 这两种方案的较小值
@ -49,7 +49,7 @@ int coinChangeDPComp(int coins[], int amt, int coinsSize) {
for (int i = 1; i <= n; i++) {
for (int a = 1; a <= amt; a++) {
if (coins[i - 1] > a) {
// 若超过背包容量,则不选硬币 i
// 若超过目标金额,则不选硬币 i
dp[a] = dp[a];
} else {
// 不选和选硬币 i 这两种方案的较小值

@ -20,7 +20,7 @@ int coinChangeIIDP(int coins[], int amt, int coinsSize) {
for (int i = 1; i <= n; i++) {
for (int a = 1; a <= amt; a++) {
if (coins[i - 1] > a) {
// 若超过背包容量,则不选硬币 i
// 若超过目标金额,则不选硬币 i
dp[i][a] = dp[i - 1][a];
} else {
// 不选和选硬币 i 这两种方案之和
@ -42,7 +42,7 @@ int coinChangeIIDPComp(int coins[], int amt, int coinsSize) {
for (int i = 1; i <= n; i++) {
for (int a = 1; a <= amt; a++) {
if (coins[i - 1] > a) {
// 若超过背包容量,则不选硬币 i
// 若超过目标金额,则不选硬币 i
dp[a] = dp[a];
} else {
// 不选和选硬币 i 这两种方案之和

@ -20,7 +20,7 @@ int coinChangeDP(vector<int> &coins, int amt) {
for (int i = 1; i <= n; i++) {
for (int a = 1; a <= amt; a++) {
if (coins[i - 1] > a) {
// 若超过背包容量,则不选硬币 i
// 若超过目标金额,则不选硬币 i
dp[i][a] = dp[i - 1][a];
} else {
// 不选和选硬币 i 这两种方案的较小值
@ -42,7 +42,7 @@ int coinChangeDPComp(vector<int> &coins, int amt) {
for (int i = 1; i <= n; i++) {
for (int a = 1; a <= amt; a++) {
if (coins[i - 1] > a) {
// 若超过背包容量,则不选硬币 i
// 若超过目标金额,则不选硬币 i
dp[a] = dp[a];
} else {
// 不选和选硬币 i 这两种方案的较小值

@ -19,7 +19,7 @@ int coinChangeIIDP(vector<int> &coins, int amt) {
for (int i = 1; i <= n; i++) {
for (int a = 1; a <= amt; a++) {
if (coins[i - 1] > a) {
// 若超过背包容量,则不选硬币 i
// 若超过目标金额,则不选硬币 i
dp[i][a] = dp[i - 1][a];
} else {
// 不选和选硬币 i 这两种方案之和
@ -40,7 +40,7 @@ int coinChangeIIDPComp(vector<int> &coins, int amt) {
for (int i = 1; i <= n; i++) {
for (int a = 1; a <= amt; a++) {
if (coins[i - 1] > a) {
// 若超过背包容量,则不选硬币 i
// 若超过目标金额,则不选硬币 i
dp[a] = dp[a];
} else {
// 不选和选硬币 i 这两种方案之和

@ -21,7 +21,7 @@ public class coin_change {
for (int i = 1; i <= n; i++) {
for (int a = 1; a <= amt; a++) {
if (coins[i - 1] > a) {
// 若超过背包容量,则不选硬币 i
// 若超过目标金额,则不选硬币 i
dp[i, a] = dp[i - 1, a];
} else {
// 不选和选硬币 i 这两种方案的较小值
@ -44,7 +44,7 @@ public class coin_change {
for (int i = 1; i <= n; i++) {
for (int a = 1; a <= amt; a++) {
if (coins[i - 1] > a) {
// 若超过背包容量,则不选硬币 i
// 若超过目标金额,则不选硬币 i
dp[a] = dp[a];
} else {
// 不选和选硬币 i 这两种方案的较小值

@ -20,7 +20,7 @@ public class coin_change_ii {
for (int i = 1; i <= n; i++) {
for (int a = 1; a <= amt; a++) {
if (coins[i - 1] > a) {
// 若超过背包容量,则不选硬币 i
// 若超过目标金额,则不选硬币 i
dp[i, a] = dp[i - 1, a];
} else {
// 不选和选硬币 i 这两种方案之和
@ -41,7 +41,7 @@ public class coin_change_ii {
for (int i = 1; i <= n; i++) {
for (int a = 1; a <= amt; a++) {
if (coins[i - 1] > a) {
// 若超过背包容量,则不选硬币 i
// 若超过目标金额,则不选硬币 i
dp[a] = dp[a];
} else {
// 不选和选硬币 i 这两种方案之和

@ -20,7 +20,7 @@ int coinChangeDP(List<int> coins, int amt) {
for (int i = 1; i <= n; i++) {
for (int a = 1; a <= amt; a++) {
if (coins[i - 1] > a) {
// i
// i
dp[i][a] = dp[i - 1][a];
} else {
// i
@ -42,7 +42,7 @@ int coinChangeDPComp(List<int> coins, int amt) {
for (int i = 1; i <= n; i++) {
for (int a = 1; a <= amt; a++) {
if (coins[i - 1] > a) {
// i
// i
dp[a] = dp[a];
} else {
// i

@ -17,7 +17,7 @@ int coinChangeIIDP(List<int> coins, int amt) {
for (int i = 1; i <= n; i++) {
for (int a = 1; a <= amt; a++) {
if (coins[i - 1] > a) {
// i
// i
dp[i][a] = dp[i - 1][a];
} else {
// i
@ -38,7 +38,7 @@ int coinChangeIIDPComp(List<int> coins, int amt) {
for (int i = 1; i <= n; i++) {
for (int a = 1; a <= amt; a++) {
if (coins[i - 1] > a) {
// i
// i
dp[a] = dp[a];
} else {
// i

@ -23,7 +23,7 @@ func coinChangeDP(coins []int, amt int) int {
for i := 1; i <= n; i++ {
for a := 1; a <= amt; a++ {
if coins[i-1] > a {
// 若超过背包容量,则不选硬币 i
// 若超过目标金额,则不选硬币 i
dp[i][a] = dp[i-1][a]
} else {
// 不选和选硬币 i 这两种方案的较小值
@ -51,7 +51,7 @@ func coinChangeDPComp(coins []int, amt int) int {
// 倒序遍历
for a := 1; a <= amt; a++ {
if coins[i-1] > a {
// 若超过背包容量,则不选硬币 i
// 若超过目标金额,则不选硬币 i
dp[a] = dp[a]
} else {
// 不选和选硬币 i 这两种方案的较小值

@ -20,7 +20,7 @@ func coinChangeIIDP(coins []int, amt int) int {
for i := 1; i <= n; i++ {
for a := 1; a <= amt; a++ {
if coins[i-1] > a {
// 若超过背包容量,则不选硬币 i
// 若超过目标金额,则不选硬币 i
dp[i][a] = dp[i-1][a]
} else {
// 不选和选硬币 i 这两种方案之和
@ -42,7 +42,7 @@ func coinChangeIIDPComp(coins []int, amt int) int {
// 倒序遍历
for a := 1; a <= amt; a++ {
if coins[i-1] > a {
// 若超过背包容量,则不选硬币 i
// 若超过目标金额,则不选硬币 i
dp[a] = dp[a]
} else {
// 不选和选硬币 i 这两种方案之和

@ -23,7 +23,7 @@ public class coin_change {
for (int i = 1; i <= n; i++) {
for (int a = 1; a <= amt; a++) {
if (coins[i - 1] > a) {
// 若超过背包容量,则不选硬币 i
// 若超过目标金额,则不选硬币 i
dp[i][a] = dp[i - 1][a];
} else {
// 不选和选硬币 i 这两种方案的较小值
@ -46,7 +46,7 @@ public class coin_change {
for (int i = 1; i <= n; i++) {
for (int a = 1; a <= amt; a++) {
if (coins[i - 1] > a) {
// 若超过背包容量,则不选硬币 i
// 若超过目标金额,则不选硬币 i
dp[a] = dp[a];
} else {
// 不选和选硬币 i 这两种方案的较小值

@ -20,7 +20,7 @@ public class coin_change_ii {
for (int i = 1; i <= n; i++) {
for (int a = 1; a <= amt; a++) {
if (coins[i - 1] > a) {
// 若超过背包容量,则不选硬币 i
// 若超过目标金额,则不选硬币 i
dp[i][a] = dp[i - 1][a];
} else {
// 不选和选硬币 i 这两种方案之和
@ -41,7 +41,7 @@ public class coin_change_ii {
for (int i = 1; i <= n; i++) {
for (int a = 1; a <= amt; a++) {
if (coins[i - 1] > a) {
// 若超过背包容量,则不选硬币 i
// 若超过目标金额,则不选硬币 i
dp[a] = dp[a];
} else {
// 不选和选硬币 i 这两种方案之和

@ -20,7 +20,7 @@ function coinChangeDP(coins, amt) {
for (let i = 1; i <= n; i++) {
for (let a = 1; a <= amt; a++) {
if (coins[i - 1] > a) {
// 若超过背包容量,则不选硬币 i
// 若超过目标金额,则不选硬币 i
dp[i][a] = dp[i - 1][a];
} else {
// 不选和选硬币 i 这两种方案的较小值
@ -42,7 +42,7 @@ function coinChangeDPComp(coins, amt) {
for (let i = 1; i <= n; i++) {
for (let a = 1; a <= amt; a++) {
if (coins[i - 1] > a) {
// 若超过背包容量,则不选硬币 i
// 若超过目标金额,则不选硬币 i
dp[a] = dp[a];
} else {
// 不选和选硬币 i 这两种方案的较小值

@ -19,7 +19,7 @@ function coinChangeIIDP(coins, amt) {
for (let i = 1; i <= n; i++) {
for (let a = 1; a <= amt; a++) {
if (coins[i - 1] > a) {
// 若超过背包容量,则不选硬币 i
// 若超过目标金额,则不选硬币 i
dp[i][a] = dp[i - 1][a];
} else {
// 不选和选硬币 i 这两种方案之和
@ -40,7 +40,7 @@ function coinChangeIIDPComp(coins, amt) {
for (let i = 1; i <= n; i++) {
for (let a = 1; a <= amt; a++) {
if (coins[i - 1] > a) {
// 若超过背包容量,则不选硬币 i
// 若超过目标金额,则不选硬币 i
dp[a] = dp[a];
} else {
// 不选和选硬币 i 这两种方案之和

@ -18,7 +18,7 @@ def coin_change_dp(coins: list[int], amt: int) -> int:
for i in range(1, n + 1):
for a in range(1, amt + 1):
if coins[i - 1] > a:
# 若超过背包容量,则不选硬币 i
# 若超过目标金额,则不选硬币 i
dp[i][a] = dp[i - 1][a]
else:
# 不选和选硬币 i 这两种方案的较小值
@ -38,7 +38,7 @@ def coin_change_dp_comp(coins: list[int], amt: int) -> int:
# 正序遍历
for a in range(1, amt + 1):
if coins[i - 1] > a:
# 若超过背包容量,则不选硬币 i
# 若超过目标金额,则不选硬币 i
dp[a] = dp[a]
else:
# 不选和选硬币 i 这两种方案的较小值

@ -17,7 +17,7 @@ def coin_change_ii_dp(coins: list[int], amt: int) -> int:
for i in range(1, n + 1):
for a in range(1, amt + 1):
if coins[i - 1] > a:
# 若超过背包容量,则不选硬币 i
# 若超过目标金额,则不选硬币 i
dp[i][a] = dp[i - 1][a]
else:
# 不选和选硬币 i 这两种方案之和
@ -36,7 +36,7 @@ def coin_change_ii_dp_comp(coins: list[int], amt: int) -> int:
# 正序遍历
for a in range(1, amt + 1):
if coins[i - 1] > a:
# 若超过背包容量,则不选硬币 i
# 若超过目标金额,则不选硬币 i
dp[a] = dp[a]
else:
# 不选和选硬币 i 这两种方案之和

@ -18,7 +18,7 @@ fn coin_change_dp(coins: &[i32], amt: usize) -> i32 {
for i in 1..=n {
for a in 1..=amt {
if coins[i - 1] > a as i32 {
// 若超过背包容量,则不选硬币 i
// 若超过目标金额,则不选硬币 i
dp[i][a] = dp[i - 1][a];
} else {
// 不选和选硬币 i 这两种方案的较小值
@ -41,7 +41,7 @@ fn coin_change_dp_comp(coins: &[i32], amt: usize) -> i32 {
for i in 1..=n {
for a in 1..=amt {
if coins[i - 1] > a as i32 {
// 若超过背包容量,则不选硬币 i
// 若超过目标金额,则不选硬币 i
dp[a] = dp[a];
} else {
// 不选和选硬币 i 这两种方案的较小值

@ -17,7 +17,7 @@ fn coin_change_ii_dp(coins: &[i32], amt: usize) -> i32 {
for i in 1..=n {
for a in 1..=amt {
if coins[i - 1] > a as i32 {
// 若超过背包容量,则不选硬币 i
// 若超过目标金额,则不选硬币 i
dp[i][a] = dp[i - 1][a];
} else {
// 不选和选硬币 i 这两种方案的较小值
@ -38,7 +38,7 @@ fn coin_change_ii_dp_comp(coins: &[i32], amt: usize) -> i32 {
for i in 1..=n {
for a in 1..=amt {
if coins[i - 1] > a as i32 {
// 若超过背包容量,则不选硬币 i
// 若超过目标金额,则不选硬币 i
dp[a] = dp[a];
} else {
// 不选和选硬币 i 这两种方案的较小值

@ -18,7 +18,7 @@ func coinChangeDP(coins: [Int], amt: Int) -> Int {
for i in stride(from: 1, through: n, by: 1) {
for a in stride(from: 1, through: amt, by: 1) {
if coins[i - 1] > a {
// i
// i
dp[i][a] = dp[i - 1][a]
} else {
// i
@ -40,7 +40,7 @@ func coinChangeDPComp(coins: [Int], amt: Int) -> Int {
for i in stride(from: 1, through: n, by: 1) {
for a in stride(from: 1, through: amt, by: 1) {
if coins[i - 1] > a {
// i
// i
dp[a] = dp[a]
} else {
// i

@ -17,7 +17,7 @@ func coinChangeIIDP(coins: [Int], amt: Int) -> Int {
for i in stride(from: 1, through: n, by: 1) {
for a in stride(from: 1, through: amt, by: 1) {
if coins[i - 1] > a {
// i
// i
dp[i][a] = dp[i - 1][a]
} else {
// i
@ -38,7 +38,7 @@ func coinChangeIIDPComp(coins: [Int], amt: Int) -> Int {
for i in stride(from: 1, through: n, by: 1) {
for a in stride(from: 1, through: amt, by: 1) {
if coins[i - 1] > a {
// i
// i
dp[a] = dp[a]
} else {
// i

@ -20,7 +20,7 @@ function coinChangeDP(coins: Array<number>, amt: number): number {
for (let i = 1; i <= n; i++) {
for (let a = 1; a <= amt; a++) {
if (coins[i - 1] > a) {
// 若超过背包容量,则不选硬币 i
// 若超过目标金额,则不选硬币 i
dp[i][a] = dp[i - 1][a];
} else {
// 不选和选硬币 i 这两种方案的较小值
@ -42,7 +42,7 @@ function coinChangeDPComp(coins: Array<number>, amt: number): number {
for (let i = 1; i <= n; i++) {
for (let a = 1; a <= amt; a++) {
if (coins[i - 1] > a) {
// 若超过背包容量,则不选硬币 i
// 若超过目标金额,则不选硬币 i
dp[a] = dp[a];
} else {
// 不选和选硬币 i 这两种方案的较小值

@ -19,7 +19,7 @@ function coinChangeIIDP(coins: Array<number>, amt: number): number {
for (let i = 1; i <= n; i++) {
for (let a = 1; a <= amt; a++) {
if (coins[i - 1] > a) {
// 若超过背包容量,则不选硬币 i
// 若超过目标金额,则不选硬币 i
dp[i][a] = dp[i - 1][a];
} else {
// 不选和选硬币 i 这两种方案之和
@ -40,7 +40,7 @@ function coinChangeIIDPComp(coins: Array<number>, amt: number): number {
for (let i = 1; i <= n; i++) {
for (let a = 1; a <= amt; a++) {
if (coins[i - 1] > a) {
// 若超过背包容量,则不选硬币 i
// 若超过目标金额,则不选硬币 i
dp[a] = dp[a];
} else {
// 不选和选硬币 i 这两种方案之和

@ -18,7 +18,7 @@ fn coinChangeDP(comptime coins: []i32, comptime amt: usize) i32 {
for (1..n + 1) |i| {
for (1..amt + 1) |a| {
if (coins[i - 1] > @as(i32, @intCast(a))) {
// i
// i
dp[i][a] = dp[i - 1][a];
} else {
// i
@ -45,7 +45,7 @@ fn coinChangeDPComp(comptime coins: []i32, comptime amt: usize) i32 {
for (1..n + 1) |i| {
for (1..amt + 1) |a| {
if (coins[i - 1] > @as(i32, @intCast(a))) {
// i
// i
dp[a] = dp[a];
} else {
// i

@ -17,7 +17,7 @@ fn coinChangeIIDP(comptime coins: []i32, comptime amt: usize) i32 {
for (1..n + 1) |i| {
for (1..amt + 1) |a| {
if (coins[i - 1] > @as(i32, @intCast(a))) {
// i
// i
dp[i][a] = dp[i - 1][a];
} else {
// i
@ -38,7 +38,7 @@ fn coinChangeIIDPComp(comptime coins: []i32, comptime amt: usize) i32 {
for (1..n + 1) |i| {
for (1..amt + 1) |a| {
if (coins[i - 1] > @as(i32, @intCast(a))) {
// i
// i
dp[a] = dp[a];
} else {
// i

@ -30,15 +30,15 @@
那么,如何处理对角线约束呢?设棋盘中某个格子的行列索引为 $(row, col)$ ,选定矩阵中的某条主对角线,我们发现该对角线上所有格子的行索引减列索引都相等,**即对角线上所有格子的 $row - col$ 为恒定值**。
也就是说,如果两个格子满足 $row_1 - col_1 = row_2 - col_2$ ,则它们一定处在同一条主对角线上。利用该规律,我们可以借助下图所示的数组 `diag1` ,记录每条主对角线上是否有皇后。
也就是说,如果两个格子满足 $row_1 - col_1 = row_2 - col_2$ ,则它们一定处在同一条主对角线上。利用该规律,我们可以借助下图所示的数组 `diags1` ,记录每条主对角线上是否有皇后。
同理,**次对角线上的所有格子的 $row + col$ 是恒定值**。我们同样也可以借助数组 `diag2` 来处理次对角线约束。
同理,**次对角线上的所有格子的 $row + col$ 是恒定值**。我们同样也可以借助数组 `diags2` 来处理次对角线约束。
![处理列约束和对角线约束](n_queens_problem.assets/n_queens_cols_diagonals.png)
### 代码实现
请注意,$n$ 维方阵中 $row - col$ 的范围是 $[-n + 1, n - 1]$ $row + col$ 的范围是 $[0, 2n - 2]$ ,所以主对角线和次对角线的数量都为 $2n - 1$ ,即数组 `diag1` 和 `diag2` 的长度都为 $2n - 1$ 。
请注意,$n$ 维方阵中 $row - col$ 的范围是 $[-n + 1, n - 1]$ $row + col$ 的范围是 $[0, 2n - 2]$ ,所以主对角线和次对角线的数量都为 $2n - 1$ ,即数组 `diags1` 和 `diags2` 的长度都为 $2n - 1$ 。
```src
[file]{n_queens}-[class]{}-[func]{n_queens}

@ -32,7 +32,7 @@
[file]{iteration}-[class]{}-[func]{while_loop}
```
`while` 循环中,由于初始化和更新条件变量的步骤是独立在循环结构之外的,**因此它比 `for` 循环的自由度更高**
**`while` 循环比 `for` 循环的自由度更高**。在 `while` 循环中,我们可以自由设计条件变量的初始化和更新步骤
例如在以下代码中,条件变量 $i$ 每轮进行了两次更新,这种情况就不太方便用 `for` 循环实现。

Loading…
Cancel
Save