采用DFS,每一层递归都是去选择某个木棍去组成一个长木棍。如果能够将小木棍全部用完而且长木棍也正好拼凑成整数的话就可以。这时候可以从小到大进行验证如果某个长木棍的长度可以满足条件那么就是答案。但是直接进行DFS会超时需要进行剪枝。
先将木棍从大到小排序,让每一个长木棍里面的小木棍都从大到小排序。
1、如果长木棍的长度不能整除于木棍的总长度的话直接跳过。
2、如果当前需要调整的木棍在长木棍的第一个的话直接跳过到上一个,因为位于第一个的是最宽松的条件。如果在第一个都不行的话后面就一定没有这个木棍放置的位置。
所以直接回到上一个木棍调整。
3、如果是一个长木棍的最后一个的话,也直接回到上一个。因为这个木棍调整的话只能用更小的两个木棍拼接起来,但这是反而使后面的拼接可能性变紧张了。
4、如果这个木棍和需要调整的木棍长度相同的话,也直接跳过。长度都相同了替换掉又有什么意义。
#include <bits/stdc++.h>


using namespace std;
const int maxn = 60+5;
int N;
bool vis[maxn];
int a[maxn];

bool DFS(int num, int len, int res, int last) {
    if (num==0&&res==0) return true;
    if (res==0) {
        res = len;last=-1;
    }
    for (int i=last+1; i<N;i++) {
        if (a[i]>res) continue;
        if (vis[i]==false) {
            vis[i] = true;
            if (DFS(num-1, len, res-a[i], i)) return true;
            vis[i] = false;
            //如果是第一根或者最后一根的话直接跳过,因为改变没有意义
            if (len==res||a[i]==res) break;
            while (a[i]==a[i+1]) i++;
        }
    }
    return false;
}

int main() {
    int max_len = 0;
    cin>>N;
    for (int i=0;i<N;i++) {
        cin>>a[i];
        max_len += a[i];
    }
    //从大到小排序
    int i;
    sort(a, a+N, greater());
    for (i=1;i<=max_len;i++) {
        memset(vis, 0, sizeof(vis));
        if (max_len%i!=0) continue;
        if (DFS(N, i, i, -1)) {
            break;
        }
    }
    cout<<i;
    return 0;
}