• POJ 1011 (DFS+剪枝)


    POJ 1011

    题目意思给你n个数,大于50的不算。让你把这n个数分成m组,每组的长度相同为len,使得这个len最短

    光用dfs写会超时,剪枝要剪很多方面

    1:优化搜索顺序 把木棍从大到小排序,优先尝试长的木棍

    2:排除等效冗余

      1.当上一个搜索失败了,下一个的数若等于上一个失败的数,那么一定失败

      2.如果在当前木棒中尝试拼第一根木棍的递归分支就失败,那么直接判断当前分支失败,立即回溯

      3.限制先后加入一

    #include <iostream>
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <map>
    #include <iomanip>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #include <set>
    #include <vector>
    //const int maxn = 1e5+5;
    #define ll long long
    ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
    
    #define MAX INT_MAX
    #define FOR(i,a,b) for( int i = a;i <= b;++i)
    #define bug cout<<"--------------"<<endl
    using namespace std;
    bool cmp(int a,int b)
    {
        return a>b;
    }
    int cnt,sum,maxx,len,n;
    int vis[500],a[500];
    
    int dfs(int k,int cab,int last)// last排除等效冗余3
    {
        if(k > cnt)
        {
            return true;
        }
        if(cab==len)
        {
            return dfs(k+1, 0 ,1);
        }
        int fail=0;   //         排除等效冗余1
        for(int i=last;i<=n;++i)   // last排除等效冗余3
        {
            if(vis[i]==0 && cab+a[i]<=len &&fail!=a[i])
            {
                vis[i]=1;
                if(dfs(k,cab+a[i],i+1))
                    return true;
                fail=a[i];
                vis[i]=0;
                if (cab==0 || cab+a[i]==len)//如果cab为0,或者相加正好是len,但是失败了,那么一定是失败了.//排除等效冗余2
                    return false;
            }
        }
        return false;
    }
    int main()
    {
        ios::sync_with_stdio(false);
    //    freopen("D:\common_text\code_stream\in.txt","r",stdin);
    //    freopen("D:\common_text\code_stream\out.txt","w",stdout);
        while(cin>>n && n)
        {
            int x=0,hhh=0;
            memset(vis,0,sizeof(vis));
            sum=0;
            maxx=0;
            cnt=0,len;
    
            FOR(i,1,n)
            {
                cin>>x;
                if(x<=50)
                {
                    hhh++;
                }
                a[hhh]=x;
                sum+=x;
                maxx=max(maxx,x);
            }
            n=hhh;
    
    
    
            sort(a+1,a+1+n,cmp);
            for(int i=maxx;i<=sum;i++)  //changdu
            {
                if(sum%i==0)
                {
                    //cout<<i<<" "<<cnt<<" "<<endl;
                    len=i;
                    cnt=sum/i;
                     memset(vis,0,sizeof(vis));
                    if(dfs(1,0,1)==1)
                        break;
                }
            }
    
            cout<<len<<endl;
        }
    
    
    }

    根原始木棒的长度是递减的(先加入x后加入y和先加入y后加入x是等效的,只需要搜索其中一种)

  • 相关阅读:
    MySQL循环插入语法
    查看linux机子的配置
    extends与implements的不区别
    Git基本命令
    VirtualBox配置 以及文件传输
    zookeeper应用场景
    oracle学习
    linux学习
    Mysql优化
    线程3
  • 原文地址:https://www.cnblogs.com/jrfr/p/11272129.html
Copyright © 2020-2023  润新知