• hdu 1455 Sticks——dfs经典的题目


    http://acm.hdu.edu.cn/showproblem.php?pid=1455

    题意:几根长度的棍子被分成了很多半。问合成多个长度相同的棍子,棍子长度最小是多少。

    题解:很明显是dfs。所以我们首先需要找到,这些棍子可能是多长,肯定是最长的棍子的长度到所有棍子长度和之间的某个长度。找到这些可能之后就直接按照这个长度开始搜。想法是搜到和为这个长度之后记录,然后重新再搜,一直到所有棍子都分配自后就完成了。

    重要的剪枝:确定每次搜索的起始位置,这个一定是确定的!!!其次就是相同长度的棍子,一个不符合其他的肯定也不符合!所以要用pre记录前面的不符合的棍子长度!

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    int a[200],vis[200],n,flag,ans,sum,ss;
    int greedy(int max,int sum);
    void dfs(int max,int pos,int value,int depth);
    bool compare(int a,int b)
    {
          return a>b;
    
    }
    int main(){
        freopen("a.txt","r",stdin);
        while(scanf("%d",&n)!=EOF&&n!=0){
            flag=ans=sum=ss=0;
            memset(a,0,sizeof(a));
            memset(vis,0,sizeof(vis));
            int max=0;
            for(int i=0;i<n;i++){
                scanf("%d",&a[i]);
                if(max<a[i]) max=a[i];
                sum+=a[i];
            }
            sort(a,a+n,compare);//从大到小排序为了方便搜索,因为很明显棍子越长他的可变性越小,所以先找长的。
            printf("%d
    ",greedy(max,sum));
        }
    return 0;
    }
    //找到有多少种棍子长度的可能性
    int greedy(int max,int sum){
        int k=0,res[1000];
        for(int i=max;i<sum;i++){
            if(sum%i==0){
            res[k]=i;
            k++;
            }
        }
        for(int i=0;i<k;i++){
                memset(vis,0,sizeof(vis));
                ss=0;
            dfs(res[i],0,0,0);
            if(ss==1) return res[i];
        }
        return sum;
    }
    void dfs(int max,int pos,int value,int depth){
        if(ss==1){
            return;
        }
        if(value==max){
            depth++;
            if(depth==sum/max){
            ss=1;
            return;
            }
             dfs(max,0,0,depth);
            return;
        }
        if(pos==n){//超过了棍子长度,说明没有可能性,所以直接返回
            return;
        }
        int pre=-1;//这里pre的用法是为了记录,当前查找的棍子是否符合,不符合的话,就记录下来,在选择其他的时候不和他相同。
        for(int i=pos;i<n;i++){
                if(!vis[i]&&a[i]+value<=max&&a[i]!=pre){
                    //首先要保证没有被访问过,其次要判断是否当前的长度加上这个之后小于目标长度,再者就是要求该棍子和前面的不一样。
                    pre=a[i];
                    vis[i]=1;
                    dfs(max,i+1,value+a[i],depth);
                    vis[i]=0;
                    if(pos==0){return;}
                    //神器的剪枝,他的神器之处在于,第一次搜索的时候第棍子的情况肯定符合!!确定了每次搜索的起始位置!!
                }
        }
    
    }
  • 相关阅读:
    插入排序(C语言版)
    2015蓝桥杯分机号(C++C组)
    2015蓝桥杯二项式
    2016蓝桥杯报纸页数(C++C组)
    区块链
    C语言学生管理系统完善版
    数据结构队列
    C语言数据结构队列
    C语言数据结构栈
    javascript 事件
  • 原文地址:https://www.cnblogs.com/Yvettey-me/p/4731445.html
Copyright © 2020-2023  润新知