我找不到解决这个问题的好方法: 我们有5< = k< = 50段,长度为1到1000个单位。 计划必须从这些细分中构建两个具有相同长度的支柱。 程序必须找到最大可能的支柱长度。
例如: 5段长度:1 5 2 3 4 正确的解决方案是:第一支柱2 + 5 = 7,第二支柱3 + 4 = 7。
你会如何处理?
答案 0 :(得分:1)
维基百科有一篇关于the Partition Problem in Computer Science的文章,其主管听起来就像你想要做的那样。
在计算机科学中,分区问题(或数字分区1) 是决定给定的多重S是否为正的任务 整数可以分成两个子集S1和S2,使得 S1中的数字之和等于S2中数字的总和。虽然 分区问题是NP完全的,有一个伪多项式 时间动态编程解决方案,并有解决方案的启发式 在许多情况下,无论是最佳还是近似的问题。对于 这个原因,它被称为"最简单的NP难问题"。
提供了几种不同的算法来提供解决方案。
另见以下内容。
Is partitioning an array into halves with equal sums P or NP?
答案 1 :(得分:0)
这是一些奇怪的代码,但这是它的工作。
(注意,没有对此代码应用优化,可能运行缓慢,
最适合小集 - x!
复杂度)
template<template<typename...> class Set = std::vector,
template<typename...> class Pair = std::pair,
template<typename...> class Cont,
typename... Ts>
inline Set<Cont<Pair<typename Cont<Ts...>::value_type, size_t>>> all_subsets(const Cont<Ts...>& cont)
{
Set<Cont<Pair<typename Cont<Ts...>::value_type, size_t>>> all_subsets;
Cont<Pair<typename Cont<Ts...>::value_type, size_t>> empty;
all_subsets.push_back(empty);
for(auto it1 = cont.begin(); it1 != cont.end(); ++it1)
{
Set<Cont<Pair<typename Cont<Ts...>::value_type, size_t>>> temp_subset = all_subsets;
for(auto& it2 : temp_subset)
it2.push_back({*it1, std::distance(cont.begin(), it1)});
for(const auto& it2 : temp_subset)
all_subsets.push_back(it2);
}
return all_subsets;
}
template<template<typename...> class Cont,
typename... Ts>
inline bool intersects_by_second(const Cont<Ts...>& first, const Cont<Ts...>& second)
{
for(auto it1 : first)
for(auto it2 : second)
if(it1 == it2)
return true;
return false;
}
template<template<typename...> class Cont,
typename... Ts>
inline Cont<typename Cont<Ts...>::value_type::first_type> make_vector_of_firsts(const Cont<Ts...> cont)
{
Cont<typename Cont<Ts...>::value_type::first_type> result;
for(const auto& it : cont)
result.push_back(it.first);
return result;
}
template<template<typename...> class Cont,
typename... Ts>
inline Cont<typename Cont<Ts...>::value_type::second_type> make_vector_of_seconds(const Cont<Ts...> cont)
{
Cont<typename Cont<Ts...>::value_type::second_type> result;
for(const auto& it : cont)
result.push_back(it.second);
return result;
}
template<template<typename...> class Bag = std::vector,
template<typename...> class Pair = std::pair,
template<typename...> class Cont,
typename... Ts>
inline Bag<Pair<Cont<Ts...>, Cont<Ts...>>> full_sum_partition(const Cont<Ts...>& cont)
{
auto subsets = all_subsets(cont);
Bag<Pair<Cont<Ts...>, Cont<Ts...>>> result;
for(auto it1 : subsets)
for(auto it2 : subsets)
{
auto it1_firsts = make_vector_of_firsts(it1);
auto it2_firsts = make_vector_of_firsts(it2);
if(std::accumulate(it1_firsts.begin(), it1_firsts.end(), 0)
==
std::accumulate(it2_firsts.begin(), it2_firsts.end(), 0))
{
if(intersects_by_second(it1, it2)
||
it1.size() != it2.size())
continue;
result.push_back(Pair<Cont<Ts...>, Cont<Ts...>>
(it1_firsts,
it2_firsts));
}
}
return result;
}
int main()
{
std::vector<int> vec{1,4,9,16,25,36,49,64};
auto result = full_sum_partition(vec);
for(const auto& x : result)
std::cout << x << " with sum " << std::accumulate(x.first.begin(),
x.first.end(),
0) << std::endl;
}
输出:
([], []) with sum 0
([1, 25, 36], [4, 9, 49]) with sum 62
([16, 25, 36], [4, 9, 64]) with sum 77
([4, 9, 49], [1, 25, 36]) with sum 62
([16, 49], [1, 64]) with sum 65
([4, 36, 49], [9, 16, 64]) with sum 89
([1, 16, 36, 49], [4, 9, 25, 64]) with sum 102
([1, 64], [16, 49]) with sum 65
([4, 9, 64], [16, 25, 36]) with sum 77
([9, 16, 64], [4, 36, 49]) with sum 89
([4, 9, 25, 64], [1, 16, 36, 49]) with sum 102
Press <RETURN> to close this window...
另请注意,我重载了运算符&lt;&lt;对于各种容器,此输出仅适用于我的其他文件。这是每个人的版本 (只是打印部分):
for(const auto& x : result)
{
size_t i=0;
std::cout << "([";
for(i=0; i< x.first.size(); ++i)
std::cout << x.first[i] << "],"[(i<x.first.size()-1)];
if(i==0)
std::cout << ']';
std::cout << ",[";
for(i=0; i< x.second.size(); ++i)
std::cout << x.second[i] << "],"[(i<x.first.size()-1)];
if(i==0)
std::cout << ']';
std::cout << ')'
<< " with sum " << std::accumulate(x.first.begin(),
x.first.end(),
0) << std::endl;
}