• Sticks<DFS>


    题意:

    给n个木棍,这些木棍是由m个长度均为L的木棍切割而来,求L的最小值。
    

    思路:

    DFS+剪枝。
    

    剪枝:

    1:L的取值范围在n(max)和n(sum)之间,逐个枚举。sum%L!=0则L不能用。
    2:sort对n个木棍长度进行由小到大排序,有以下好处:
        a:从大的开始搜索。eg:如果L8;5+3>(优势)5+2+1;把更灵活地木棍留下来。
        b:查找更有序。
    3:如果有一个木棍无法和其他木棍组合成L,则此种方案不行。<有两种情况>。
    4:如果len[i]无法和当前的木棍组成,那么如果len[i+1]=len[i],len[i+1]也不行。
    
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    int len[5005],vis[5005];
    int n,sum,num,L;
    int cmp(int a,int b)
    {
        return a>b;
    }
    int DFS(int m,int S,int N)//m代表当前已经组成的木棍数,S代表当前木棍的长度,N等会
    {
        if(m==num-1)//b:已经有num-1根木棍组合好了,那么剩下的木棍一定也可以组成一根;
            return 1;
        for(int i=N;i<n;i++){
            if(!vis[i]&&(S+len[i])==L)
            {
                vis[i]=1;
                if(DFS(m+1,0,0))
                    return 1;
                vis[i]=0;//虽然上步已经说明这条路行不通,还是要回溯回来原因是下一个else
                return 0;//C;
            }
            if(!vis[i]&&(S+len[i])<L)
            {
                vis[i]=1;
                if(DFS(m,S+len[i],i+1))
                    return 1;
                vis[i]=0;
                if(S==0)//说明剩下的木棍无法组成;
                    return 0;//D;
                while(len[i]==len[i+1])//E:此路不通,len[i]不行,如果len[i+1]=len[i],len[i+1]也不行。
                    ++i;
            }
        }
        return 0;
    }
    int main()
    {
        while(scanf("%d",&n)!=EOF)
        {
            if(n==0)
                break;
            sum=0;
            for(int i=0;i<n;i++){
                scanf("%d",&len[i]);
                sum+=len[i];
            }
            sort(len,len+n,cmp);
            for(L=len[0];L<=sum/2;L++)//a:减少L的枚举数量,如果L>sum/2,那么只能只有一根木棍
            {
                if(sum%L==0)//满足L的条件再递归
                {
                    memset(vis,0,sizeof(vis));
                    num=sum/L;
                    if(DFS(0,0,0)){
                        printf("%d
    ",L);
                        break;
                    }
                }
            }
            if(L>sum/2)
                printf("%d
    ",sum);
        }
        return 0;
    }
    想的太多,做的太少。
  • 相关阅读:
    cmd 中英文 切换
    comparable和comparator
    ORACLE 毫秒转换为日期 日期转换毫秒
    asp.net弹出对话框
    一、DataBinder.Eval的基本格式
    转载 创业
    常用的js验证数字,电话号码,传真,邮箱,手机号码,邮编,日期
    CodeSmith开发系列资料总结
    SQL函数说明大全
    SQLServer游标的使用
  • 原文地址:https://www.cnblogs.com/pealicx/p/6115635.html
Copyright © 2020-2023  润新知