洛谷P1120【小木棍】(搜索+剪枝)

描述
有 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;
}
原文地址:https://www.cnblogs.com/stargazer-cyk/p/10366424.html