回溯 +剪枝 (对剪枝要求比较高) ,一下是代码
#include <iostream>
#include <cstring>
#include <stack>
#include <algorithm>
#include <utility>
#include <functional>
using namespace std;
const int size = 200;
int get_next(int cur , int old , int *v , int *p , int num)
{
int i = cur + 1;
while(i < num)
{
if(!p[i] && v[i] != old) return i;
++i;
}
return -1;
}
int main()
{
int n;
int v[size];
int u[size];
while(cin >> n && n)
{
int sum = 0;
for(int i = 0 ; i < n ; ++i)
{
cin >> v[i];
sum += v[i];
}
sort(v , v + n , greater<int>());
for(int i = v[0] ; i <= sum ; ++i)
{
if(sum % i == 0)
{
memset(u , 0 , sizeof(int) * n);
int m = sum / i;
int now = v[0];
stack<int> s;
u[0] = 1;
s.push(0);
int over = 0 , cur = 0 , old = -1;
while(m > 1 && !s.empty())
{
if(over)
{
int t = s.top(); s.pop(); u[t] = 0; old = v[t];
if(!s.empty() && s.top() < 0)
{
while(!s.empty() && s.top() < 0)
{
s.pop(); now = i; ++m; /*break;*/
cur = s.top();
now -= v[cur];
s.pop();
u[cur] = 0;
}
}
else { cur = t; now -= v[t]; over = 0; }
continue;
}
if(now == i)
{
--m;
s.push(-1);
cur = 0;
now = 0;
}
if(now < i)
{
int r;
do{
r = get_next(cur ,old , v , u , n);
if(r < 0 ) { over = 1; break; }
cur = r;
old = v[r];
}while(now + v[r] > i);
if(!over){
old = -1;
cur = r;
now += v[r];
s.push(r);
u[r] = 1;
}
}
}
if(m <= 1) { cout << i << endl; break; }
}
}
}
return 0;
}