暴搜的思路并不难想到,主要难点是各种优化、各种剪枝:
1. 预先处理出所有木棍的总长度,且保证枚举答案的值能被总长度整除。
2. 每根木棍的长度可用桶来存储,并且预先处理出最长的和最短的木棍的长度,搜索时从最大长度到最小长度递减枚举。
3. 若拼接当前木棍时已用了一根长为X的木棍,则dfs时从长度X开始搜索。
4. 若某组拼接不成立,且此时 已拼接的长度为0 或 当前已拼接的长度与刚才枚举的长度之和为最终枚举的答案 时,则可直接跳出循环,因为此时继续枚举其它更小的值时,显然可能情况更少,且同样凑不完。
5. 注意常数不要太大。
附上代码:
```cpp
#include<cstdio>
#include<cstdlib>
const int N = 70 ;
int n , cnt , tot , maxn , minn , tm[ N ] /* 2 */ ;
void dfs( int res , int sum , int target , int p ) {
if( res == 0 ) {
printf("%d", target );
exit( 0 );
}
if( sum == target ) {
dfs( res - 1 , 0 , target , maxn );
return;
}
for( int i = p ; i >= minn ; i -- ) { // 2 3
if( tm[ i ] && i + sum <= target ) {
tm[ i ] -- ;
dfs( res , sum + i , target , i );
tm[ i ] ++ ;
if ( sum == 0 || sum + i == target ) //4
break;
}
}
return;
}
int main() {
scanf("%d" , &n ) ;
minn = N ;
int temp;
while( n -- ) {
scanf("%d" , &temp );
if( temp <= 50 ) {
cnt ++;
tm[ temp ] ++;
tot += temp;
maxn = maxn > temp ? maxn : temp ; //1
minn = minn < temp ? minn : temp ;
}
}
temp = tot >> 1;
for( int i = maxn ; i <= temp ; i ++ ) {
if( tot % i == 0 ) {
dfs( tot / i , 0 , i , maxn );
}
}
printf("%d" , tot );
return 0;
}
```