/*
有处于一个水平面的N根试管,它们倒立着通过导管循环连接,每两个试管间有一个开关。平时,各个开关均为闭合状态,使两试管间的水不流通。
当各试管中水的高度给出时,打开开关,让水流动,满足最后各试管的水位一样高。请问:如何打开才能让开关的打开数目最少?
*/
#include <iostream>
#include <vector>
#include <deque>
#include <numeric>
#include <algorithm>
#include <iterator>
using namespace std;
const double EPSINON = 0.001;
typedef vector< double > cuvette_group;
typedef cuvette_group::iterator cuvette_iterator;
typedef deque< bool > switch_group;
typedef switch_group::iterator switch_iterator;
void init(cuvette_group& cg);
int count_of_open(cuvette_group& cg, switch_group& sg, double average);
//判断sg给出的开关状态方案是否满足条件
bool good(cuvette_group& cg, switch_group& sg, double average);
//判断两个相邻的关闭的开关之间的试管能否满足条件
bool partial_good(cuvette_group& cg, switch_group& sg, switch_iterator& first, switch_iterator& last, double average);
int main()
{
cuvette_group cuvettes;
switch_group switches;
init(cuvettes);
switches.assign(cuvettes.size(), true);
double average = accumulate(cuvettes.begin(), cuvettes.end(), 0.0) / cuvettes.size();
cout << count_of_open(cuvettes, switches, average) << endl;
copy(switches.begin(), switches.end(), ostream_iterator< bool >(cout, " "));
cout << endl;
return 0;
}
void init(cuvette_group& cg)
{
for (double i = 1L; i < 10L; ++i)
{
cg.push_back(i);
}
}
int count_of_open(cuvette_group& cg, switch_group& sg, double average)
{
int ret = count(sg.begin(), sg.end(), true);
if (good(cg, sg, average))
{
for ( ; ; )
{
bool has_sub_solution = false;
switch_iterator i;
for (i = sg.begin(); i != sg.end(); ++i)
{
if (*i)
{
*i = false;
//此处需要优化……^_^,即只需要判断由此关闭开关分开的两个区间之一也满足条件
if (good(cg, sg, average))
{
has_sub_solution = true;
break;
}
*i = true;
}
}
if (has_sub_solution)
{
ret--;
}
else
{
return ret;
}
}
}
return ret;
}
bool good(cuvette_group& cg, switch_group& sg, double average)
{
if (count(sg.begin(), sg.end(), false) <= 1)
{
return true;
}
switch_iterator begin, end;
begin = end = find(sg.begin(), sg.end(), false);
for ( ; ; )
{
if (end != sg.end())
{
end = find(begin+1, sg.end(), false);
if (end != sg.end())
{
if (!partial_good(cg, sg, begin, end, average))
{
return false;
}
begin = end;
}
else
{
break;
}
}
}
return true;
}
bool partial_good(cuvette_group& cg, switch_group& sg, switch_iterator& first, switch_iterator& last, double average)
{
cuvette_iterator cbegin(cg.begin()), cend(cg.begin());
advance(cbegin, distance(sg.begin(), first)+1);
advance(cend, distance(sg.begin(), last)+1);
double temp = accumulate(cbegin, cend, 0.0) - average * (distance(cbegin, cend));
return (temp >= -EPSINON) && (temp <= EPSINON);
}