Files
exercises/pojcs101_T01011_sticks.cpp
T
2026-08-06 23:20:25 +08:00

116 lines
4.6 KiB
C++

#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
using namespace std;
template <typename T>
void log_vector(const vector<T>& vec, const string& prefix = "") {
clog << prefix;
for (const T i : vec) { clog << i << " "; }
clog << endl;
}
vector<int> get_divisors(const int n) {
vector<int> small_divisors = {1};
vector<int> big_factors = {n};
for (int i = 2; i * i <= n; i++) {
if (n % i == 0) {
small_divisors.push_back(i);
big_factors.push_back(n / i);
}
}
// reverse(small_divisors.begin(), small_divisors.end());
// big_factors.insert(big_factors.end(), small_divisors.begin(), small_divisors.end());
// return big_factors;
reverse(big_factors.begin(), big_factors.end());
small_divisors.insert(small_divisors.end(), big_factors.begin(), big_factors.end());
return small_divisors;
}
bool verify_length_dfs(const vector<int>& sorted_cut_sticks,
const int target_length,
const int remaining_length,
const int original_sticks,
const int remaining_sticks,
size_t global_right_idx,
const size_t right_idx,
vector<bool>& used
) {
// clog << "verify_length_dfs(" << target_length << ") " << remaining_length << " " << remaining_sticks << "x " <<
// global_right_idx << "->" << right_idx << endl;
// log_vector(used, "used: ");
if (remaining_sticks == 0) { return true; }
bool result = false;
for (int i = static_cast<int>(right_idx); i >= 0; i--) {
if (target_length < sorted_cut_sticks[i]) { return false; }
if (used[i]) { continue; }
if (remaining_length < sorted_cut_sticks[i]) { continue; }
used[i] = true;
if (remaining_length == sorted_cut_sticks[i]) { // 下一根
result = verify_length_dfs(sorted_cut_sticks, target_length, target_length, original_sticks,
remaining_sticks - 1, global_right_idx,
global_right_idx, used);
} else { // 这一根
if (remaining_length == target_length) { // 这一根的第一节
global_right_idx = i;
}
result = verify_length_dfs(sorted_cut_sticks, target_length,
remaining_length - sorted_cut_sticks[i], original_sticks,
remaining_sticks, global_right_idx, i, used);
}
if (result) { return true; }
used[i] = false;
while (i >= 0 && sorted_cut_sticks[i] == sorted_cut_sticks[i - 1]) { i--; } // 剪枝
// if (remaining_sticks == original_sticks && remaining_length == target_length) { return false; } // 剪枝
if (remaining_length == target_length) { return false; } // 剪枝
}
return false;
}
/// 需要保证 sorted_cut_sticks 有序;需要保证 target_length * remaining_sticks = 总长度
bool verify_length_dfs(const vector<int>& sorted_cut_sticks,
const int target_length,
const int remaining_sticks) {
vector<bool> used(sorted_cut_sticks.size(), false);
bool result = verify_length_dfs(sorted_cut_sticks, target_length, target_length, remaining_sticks,
remaining_sticks, sorted_cut_sticks.size() - 1, sorted_cut_sticks.size() - 1, used);
// log_vector(used, "used: ");
return result;
}
int get_shortest_original_length(vector<int> cut_sticks) {
sort(cut_sticks.begin(), cut_sticks.end());
const int total_length = accumulate(cut_sticks.begin(), cut_sticks.end(), 0);
const vector<int> divisors = get_divisors(total_length);
log_vector(divisors, "divisors: ");
for (const int divisor : divisors) {
if (verify_length_dfs(cut_sticks, divisor, total_length / divisor)) {
return divisor;
}
}
return -1;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int cut_sticks_amount;
while (cin >> cut_sticks_amount && cut_sticks_amount) {
vector<int> cut_sticks(cut_sticks_amount);
for (int i = 0; i < cut_sticks_amount; i++) {
cin >> cut_sticks[i];
}
sort(cut_sticks.begin(), cut_sticks.end());
log_vector(cut_sticks, "cut_sticks: ");
// int target_length;
// cin >> target_length;
// cout << (verify_length_greedy(cut_sticks, target_length) ? "Yes" : "No") << endl;
cout << get_shortest_original_length(cut_sticks) << endl;
}
return 0;
}