2021-07-11 06:43:45 +02:00
|
|
|
/*
|
|
|
|
* @brief [Magic sequence](https://www.csplib.org/Problems/prob019/)
|
|
|
|
*
|
|
|
|
* @details
|
|
|
|
*
|
|
|
|
* @author [Jxtopher](https://github.com/jxtopher)
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
#include <cassert>
|
|
|
|
#include <iostream>
|
|
|
|
#include <list>
|
|
|
|
#include <numeric>
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
namespace backtracking {
|
|
|
|
namespace magic_sequence {
|
2021-07-11 22:52:18 +02:00
|
|
|
using sequence_t = std::vector<unsigned int>;
|
2021-07-11 06:43:45 +02:00
|
|
|
|
2021-07-11 22:52:18 +02:00
|
|
|
void print(const sequence_t& s) {
|
|
|
|
for (const auto& item : s) std::cout << item << " ";
|
|
|
|
std::cout << std::endl;
|
|
|
|
}
|
2021-07-11 06:43:45 +02:00
|
|
|
|
2021-07-11 22:52:18 +02:00
|
|
|
// Check if it's a magic sequence
|
|
|
|
bool is_magic(const sequence_t& s) {
|
|
|
|
for (unsigned int i = 0; i < s.size(); i++) {
|
|
|
|
if (std::count(s.cbegin(), s.cend(), i) != s[i])
|
|
|
|
return false;
|
2021-07-11 06:43:45 +02:00
|
|
|
}
|
2021-07-11 22:52:18 +02:00
|
|
|
return true;
|
|
|
|
}
|
2021-07-11 06:43:45 +02:00
|
|
|
|
2021-07-11 22:52:18 +02:00
|
|
|
// Filtering of sub-solutions
|
|
|
|
// true if the sub-solution is valid otherwise false
|
|
|
|
bool filtering(const sequence_t& s, unsigned int depth) {
|
|
|
|
return std::accumulate(s.cbegin(), s.cbegin() + depth,
|
|
|
|
static_cast<unsigned int>(0)) <= s.size();
|
|
|
|
}
|
2021-07-11 06:43:45 +02:00
|
|
|
|
2021-07-11 22:52:18 +02:00
|
|
|
void solve(sequence_t* s, std::list<sequence_t>* ret, unsigned int depth = 0) {
|
|
|
|
if (depth == s->size()) {
|
|
|
|
if (is_magic(*s))
|
|
|
|
ret->push_back(*s);
|
|
|
|
} else {
|
|
|
|
for (unsigned int i = 0; i < s->size(); i++) {
|
|
|
|
(*s)[depth] = i;
|
|
|
|
if (filtering(*s, depth + 1))
|
|
|
|
solve(s, ret, depth + 1);
|
2021-07-11 06:43:45 +02:00
|
|
|
}
|
|
|
|
}
|
2021-07-11 22:52:18 +02:00
|
|
|
}
|
2021-07-11 06:43:45 +02:00
|
|
|
|
2021-07-11 22:52:18 +02:00
|
|
|
} // namespace magic_sequence
|
2021-07-11 06:43:45 +02:00
|
|
|
|
2021-07-11 22:52:18 +02:00
|
|
|
} // namespace backtracking
|
2021-07-11 06:43:45 +02:00
|
|
|
|
|
|
|
using namespace backtracking::magic_sequence;
|
|
|
|
|
|
|
|
static void test() {
|
|
|
|
sequence_t s_magic = {6, 2, 1, 0, 0, 0, 1, 0, 0, 0};
|
|
|
|
assert(is_magic(s_magic));
|
|
|
|
|
|
|
|
sequence_t s_not_magic = {5, 2, 1, 0, 0, 0, 1, 0, 0, 0};
|
|
|
|
assert(!is_magic(s_not_magic));
|
|
|
|
}
|
|
|
|
|
|
|
|
int main() {
|
|
|
|
test();
|
|
|
|
|
2021-07-11 22:52:18 +02:00
|
|
|
for (unsigned int i = 2; i < 12; i++) {
|
2021-07-11 06:43:45 +02:00
|
|
|
std::cout << "Solution for n = " << i << std::endl;
|
2021-07-11 22:52:18 +02:00
|
|
|
std::list<sequence_t>* r1 = new std::list<sequence_t>();
|
|
|
|
sequence_t* s1 = new sequence_t(i, i);
|
2021-07-11 06:43:45 +02:00
|
|
|
solve(s1, r1);
|
2021-07-11 22:52:18 +02:00
|
|
|
for (const auto& item : *r1) print(item);
|
2021-07-11 06:43:45 +02:00
|
|
|
}
|
|
|
|
}
|