zoukankan      html  css  js  c++  java
  • 洛谷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;
    }
    
  • 相关阅读:
    X lvm管理:扩展lv、删除pv、lv,删除物理卷PV
    X 如何在Linux中缩小LVM大小(逻辑卷调整)如何在Linux中缩小LVM大小(逻辑卷调整)
    元素和为目标值的子矩阵数量
    完美矩形问题
    桶排序算法
    组合数组合
    求两个有序数组的第k大的数(默认两有序数组都为从小到大)
    二叉树的遍历
    卡特兰数
    二叉排序树
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/10366424.html
Copyright © 2011-2022 走看看