Skip to content

Commit

Permalink
feat: add golden_0812
Browse files Browse the repository at this point in the history
finish pure-eight-queen problem

Signed-off-by: Certseeds <51754303+Certseeds@users.noreply.github.com>
  • Loading branch information
Certseeds committed Feb 26, 2024
1 parent 661ccd3 commit 37d2d65
Show file tree
Hide file tree
Showing 3 changed files with 186 additions and 1 deletion.
2 changes: 1 addition & 1 deletion algorithm/array/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ list(APPEND leetcode_order 944 977 985 986 989)
list(APPEND leetcode_order 999 1010 1013 1030 1051)
list(APPEND leetcode_order 1089 1108 1170 1184 1200)
list(APPEND leetcode_order 1217 1329 1360 1365 1371)
list(APPEND leetcode_order 1391)
list(APPEND leetcode_order 1391 golden_0812)
LIST(TRANSFORM leetcode_order PREPEND leetcode_)

set(dependencies ${dependencies} ${leetcode_order})
Expand Down
123 changes: 123 additions & 0 deletions algorithm/array/leetcode_golden_0812.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@

// SPDX-License-Identifier: AGPL-3.0-or-later
/*
CS203_DSAA_template
Copyright (C) 2022-2023 nanoseeds
*/
#include "leetcode_golden_0812_test.hpp"
#include <unordered_map>
#include <stack>

namespace leetcode_golden_0812 {
using std::unordered_map;

bool check(const vector<vector<int32_t>> &nums, int32_t i, int32_t j) {
const auto length = static_cast<int32_t>(nums.size());
for (int32_t x{0}; x < length; x++) {
if (x != j && nums[i][x] == 1) {
return false;
}
if (x != i && nums[x][j] == 1) {
return false;
}
}
for (int32_t x{i + 1}, y{j + 1}; x < length && y < length; x++, y++) {
if (nums[x][y] == 1) {
return false;
}
}
for (int32_t x{i - 1}, y{j - 1}; x >= 0 && y >= 0; x--, y--) {
if (nums[x][y] == 1) {
return false;
}
}
for (int32_t x{i - 1}, y{j + 1}; x >= 0 && y < length; x--, y++) {
if (nums[x][y] == 1) {
return false;
}
}
for (int32_t x{i + 1}, y{j - 1}; x < length && y >= 0; x++, y--) {
if (nums[x][y] == 1) {
return false;
}
}
return true;
}

void store(const vector<vector<int32_t>> &nums, vector<vector<string>> &insert) {
const auto length = nums.size();
insert.emplace_back();
for (size_t i{0}; i < length; i++) {
string line(length, '.');
for (size_t j{0}; j < length; j++) {
if (nums[i][j] == 1) {
line[j] = 'Q';
}
}
insert.back().push_back(line);
}
}

vector<vector<string>> leetcode_golden_0812::solveNQueen(int32_t n) {
if (n == 1) {
return {{"Q"}};
} else if (n < 4) {
return {};
}
assert(n > 3);
// 感觉这里的思路应该用递归比较好, 对于每一个n, 我们假设n-1已经解决了, 对于每一种情况来说,有左上 左下 右上 右下四个拓展情况, 每种拓展情况有2n-1个类型,
// 通过(n-1)^2的时间复杂度visit获取其
// 但是八皇后问题不能这样递推, 因为不是所有n皇后问题都能够简化出一个n-1皇后的区域, 倒不如说能规约出来的才比较少见.
// 使用回溯的方式来计算,
vector<vector<string>> will_return{};
vector<vector<int32_t>> visit(n, vector<int32_t>(n, 0));
int32_t i{0}, j{0};
int32_t count{0};
std::stack<int32_t> sta{};
// 需要返回的数组只不过是一个{(x1,y1),(x2,y2)....}的映射, 所以不需要存储那个, 只需要存每个皇后的坐标即可, 也方便之后进行去重.
while (i < n && j < n) {
if (visit[i][j] == 0) {
visit[i][j] = 1;
} // this can be a queen.
// then should filter all the other positions, line, row and diagonal.
// 或者是不存储只是尝试?
// 对(i,j)尝试放一个, 接下来对(i+1,0 to n-1)进行挨个尝试, 每个判定一次, 如果都不行, 则回退i并j+1.
// 大概n^3
if (check(visit, i, j)) {
if (i + 1 < n) {
i++;
sta.push(j);
j = 0;
continue;
} else {
store(visit, will_return);
// should get the last i
}
}
visit[i][j] = 0;
if (j + 1 < n) {
j++;
} else if (j + 1 == n) {
i--;
j = sta.top();
sta.pop();
if (i == 0 && j + 1 >= n) {
break;
}
while (j + 1 == n) {
visit[i][j] = 0;
i--;
j = sta.top();
sta.pop();
}
visit[i][j] = 0;
j += 1;
}

}
return will_return;
}

}
62 changes: 62 additions & 0 deletions algorithm/array/leetcode_golden_0812_test.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
/*
CS203_DSAA_template
Copyright (C) 2022-2023 nanoseeds
*/
//@Tag array
//@Tag 数组
#ifndef CS203_DSAA_TEMPLATE_ALGORITHM_ARRAY_LEETCODE_golden_0812_TEST_HPP
#define CS203_DSAA_TEMPLATE_ALGORITHM_ARRAY_LEETCODE_golden_0812_TEST_HPP

#include <catch_main.hpp>
#include <cstdint>
#include <cstddef>
#include <vector>
#include <array>

namespace leetcode_golden_0812 {
using std::vector;
using std::array;

namespace leetcode_golden_0812 {
vector<vector<string>> solveNQueen(int32_t n);
}

using Catch::Matchers::UnorderedEquals;

TEST_CASE("test case 1 [test_golden_0812]", "[test_golden_0812]") {
constexpr const int32_t input{1};
const vector<vector<string>> result{{"Q"}};
CHECK_THAT(result,
UnorderedEquals(leetcode_golden_0812::solveNQueen(input)));
}

TEST_CASE("test case 2 3 [test_golden_0812]", "[test_golden_0812]") {
CHECK_THAT(vector<vector<string>>{},
UnorderedEquals(leetcode_golden_0812::solveNQueen(2)));

CHECK_THAT(vector<vector<string>>{},
UnorderedEquals(leetcode_golden_0812::solveNQueen(3)));
}

TEST_CASE("test case 5 [test_golden_0812]", "[test_golden_0812]") {
CHECK_THAT((vector<vector<string>>{{
".Q..",
"...Q",
"Q...",
"..Q.",

},
{
"..Q.",
"Q...",
"...Q",
".Q..",

}}),
UnorderedEquals(leetcode_golden_0812::solveNQueen(4)));
}
}
#endif //CS203_DSAA_TEMPLATE_ALGORITHM_ARRAY_LEETCODE_golden_0812_TEST_HPP

0 comments on commit 37d2d65

Please sign in to comment.