• poj 1011 Sticks(经典DFS+剪枝)


    题意:给出n根小棒的长度stick[i],已知这n根小棒原本由若干根长度相同的长木棒(原棒)分解而来。求出原棒的最小可能长度。

    先说先具体的实现:求出总长度sum和小棒最长的长度max,则原棒可能的长度必在max~sum之间,然后从小到大枚举max~sum之间能被sum整除的长度len,用dfs求出所有的小棒能否拼凑成这个长度,如果可以,第一个len就是答案。

    下面就是关键的了,就是这道题dfs的实现和剪枝的设计:

          1.以一个小棒为开头,用dfs看看能否把这个小棒拼凑成len长,如果可以,用vis[i]记录下用过的小棒,然后继续以另外一个小棒为开头,以此类推。

          2.小棒的长度从大到小排序,这个就不解释了。

          3.如果当前最长的小棒不能拼成len长,那么就返回前一步,更改前一步的最长小棒的组合情况(这里不能是全部退出),不用再继续搜索下去了。

          4.最重要的,就是比如说17,9,9,9,9,8,8,5,2……如果当前最长小棒为17,它与第一个9组合之后dfs发现不能拼成len,那么17就不用和后面所有的9组合了,而直接和8开始组合。这个剪枝直接从TLE到16MS,很强大。

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    int s[100],vis[100];
    int n,num,len;
    
    int cmp(int a,int b)
    {
        return a>b;
    }
    
    int DFS(int cur,int k,int cnt)
    {
        if(cnt==num) return 1;
        if(cur==len) return DFS(0,0,cnt+1);
        int pre=0;//pre用来计算重复长度的木棍(剪枝)
        int i;
        for(i=k;i<n;i++)
        {
            if(vis[i]==0&&s[i]+cur<=len&&s[i]!=pre)
            {
                pre=s[i];
                vis[i]=1;
                if(DFS(s[i]+cur,i+1,cnt))
                    break;
                vis[i]=0;
                if(k==0) return 0;
            }
        }
        if(i==n) return 0;
        else return 1;
    }
    
    int main()
    {
        while(cin>>n&&n!=0)
        {
            int sum=0;
            for(int i=0;i<n;i++)
            {
                cin>>s[i];
                sum+=s[i];
            }
            sort(s,s+n,cmp);
            for(len=s[0];len<=sum/2;len++)
            {
                if(sum%len==0)
                {
                    num=sum/len;
                    memset(vis,0,sizeof(vis));
                    if(DFS(0,0,0))
                        break;
                }
            }
            if(len>sum/2) cout<<sum<<endl;
            else cout<<len<<endl;
    
        }
        return 0;
    }
  • 相关阅读:
    java 获取json字符串中key对应的值
    location.href跳转页面时传递参数并且在新页面接收参数
    bootstrap table 合并列(只合并相邻的相同项)
    谷歌浏览器输入框清除历史输入记录
    js高德地图支持,java获取高德地图两点间的距离
    ASP.NET Excel 文件导入与导出实例
    Struts2入门---输入验证---验证身份证案例
    Struts2入门---国际化
    Struts2入门---消息处理和类型转换
    Struts2入门---增删改查- 拦截器栈的应用
  • 原文地址:https://www.cnblogs.com/Fy1999/p/9057512.html
Copyright © 2020-2023  润新知