描述
有 n 根木棒,你需要将它们分成尽量多的组, 满足每组木棒长度和相等。你不能 将木棒砍断。 输出最优方案下一组中木棒长度之和。
输入
第一行一个整数 n
接下来 n 个整数,表示 n 根木棒的长度
输出
一行一个整数,表示木棒长度之和
样例输入
4
2 5 3 4
样例输出
7
提示
70%的数据保证 n<=8
100%的数据保证 n<=50
我看洛谷上有数据加强版
疯狂剪枝
枚举组数
然后不断拼起来,看能不能拼出那么多组
#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
inline int read(){
char ch=getchar();
int res=0;
while(!isdigit(ch))ch=getchar();
while(isdigit(ch)) res=(res<<1)+(res<<3)+(ch^48),ch=getchar();
return res;
}
int a[70],n,len,sum;
bool vis[70];
inline bool comp(int u,int v){
return u>v;
}
inline bool dfs(int p,int l,int s){//p是枚举到第几根木棍,l是当前这根已经拼了多长,s是已经拼的数量
if(l>len)return false;
if(s==sum)return true;
if(l==len){
if(s+len==sum)return true;
for(p=1;p<=n&&vis[p];p++);
vis[p]=true;
if(dfs(p+1,a[p],s+len)){
vis[p]=false;
return true;
}
vis[p]=false;
return false;
}
for(;p<=n;p++){
if(!vis[p]&&(a[p]!=a[p-1]||vis[p-1])){
vis[p]=true;
if(dfs(p+1,l+a[p],s)){
vis[p]=false;
return true;
}
vis[p]=false;
if(l+a[p]==len||l==0)break;//不知道为什么这个剪枝很管用
while(a[p]==a[p+1])p++;
}
}
return false;
}
int main(){
n=read();
for(int i=1;i<=n;++i){
a[i]=read();
if(a[i]>50){
n--,i--;
continue;
}
sum+=a[i];
len=max(len,a[i]);
}
sort(a+1,a+n+1,comp);
for(;len<=sum/2;++len){
if(sum%len==0){
vis[1]=true;
if(dfs(1,a[1],0)){
cout<<len;
return 0;
}
}
}
cout<<sum;
}