• Stick ------ 剪枝神题


    这个是自己剪得 , 我感觉已经很不错了  但是不知道哪里出了问题  一直  超时

    //  根据所给答案 和 题目要求 最直观的就可以有剪枝的地方 而且 剪枝剪得越早 就越省时省力
    //  好的思路也可以省不少的时间
    #include<stdio.h>
    #include<string.h>
    #include<math.h>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #include<set>
    #include<stack>
    #include<string>
    #include<sstream>
    #include<map>
    #include<cctype>
    using namespace std;
    bool cmp(int a,int b)
    {
        return a>b;
    }
    int a[55],goal,visited[55],mark,result,sum,n,flag;
    void DFS_check()    //  我感觉 前面的两个剪枝 就十分的强悍了   但是鉴于  这一道题 比较的 变态 所以  继续剪枝!
    {
        if(flag)
            return ;
        if(goal>result)
            return ;
        if(goal==result) //  加上了最后一个数字  这时候 mark 也刚刚好  所以 这个放上面
        {
            mark++;
            goal=0;         //  攒够 一套之后 就直接让 计数器归零
        }
        if(mark*result==sum)//  这时候  是 刚好符合条件    //  这个值 不可能大于 sum
        {
            flag=1;
        }
        for(int i=0;i<n;i++)
        {
            if(!visited[i])     // 没有被访问过
            {
                visited[i]=1;
                goal+=a[i];
                DFS_check();
                goal-=a[i];
                visited[i]=0;
                while(a[i]==a[i+1])
                    i++;
            }
        }
    
        if(flag)
            return ;
    }
    int main()
    {
        while(scanf("%d",&n),n)
        {
            result=sum=0;
            for(int i=0;i<n;i++)
            {
                scanf("%d",&a[i]);
                sum+=a[i];
            }
            sort(a,a+n,cmp);   // 将 碎木棒长度 从大到小排序之后 1 :方便操作 2 :在找出答案之后 可以很快的退出 寻找 ,能省不少的时间
            int len=(sum/2)+1;
            for(int i=a[0];i<=len;i++)   //  一个剪枝   ,  这个估计能省去 理论上一半的时间 的时间
            {
                if(sum%i!=0)    //  这里的 i 是假设的 原始木棒长度 //  如果总长度 不能被假设木棒长度整除的话 , 这个假设就是不成立的 .
                    continue;
                memset(visited,0,sizeof(visited));
                flag=goal=mark=0;
                result=i;
                DFS_check();
                if(flag)   //  检查 该长度  是否  是  最小的木棒长度
                {
                    result=i;     //更新最小木棒长度
                    break;
                }
            }
            if(result==0)
                result=sum;
            printf("%d
    ",result);
        }
        return 0;
    }

     下面附上正确答案

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<math.h>
     4 #include<iostream>
     5 #include<algorithm>
     6 #include<queue>
     7 #include<vector>
     8 #include<set>
     9 #include<stack>
    10 #include<string>
    11 #include<sstream>
    12 #include<map>
    13 #include<cctype>
    14 using namespace std;
    15 int n,sum,a[100],goal,visited[100];
    16 bool cmp(int a,int b)
    17 {
    18     return a>b;
    19 }
    20 bool DFS(int now,int index,int mark,int goal)  // mark 已集齐的 原始木棒数量   goal 假设原始木棒长度
    21 {
    22     if(mark*goal==sum)
    23         return true;
    24     for(int i=index;i<n;i++)
    25     {
    26         if(visited[i]||(a[i]==a[i-1]&&!visited[i-1]))  //如果这一个节点 已经 被用了   就不再用了  //如果这个节点和上一个节点相同  并且上一个节点 没有被使用  那么这个节点就也不会被使用了
    27             continue;               //  因为  出现这种情况 的原因只有一种就是 + 这个数值  now 大于了 目标值 
    28         if(now+a[i]==goal)
    29         {
    30             visited[i]=1;
    31             if(DFS(0,0,mark+1,goal))
    32                 return true;
    33             visited[i]=0;
    34             return false;
    35         }
    36         else
    37         if(now+a[i]<goal)
    38         {
    39             visited[i]=1;
    40             if(DFS(now+a[i],i+1,mark,goal))   //    在已经确定了一个比较大的值之后  继续向后面寻找比较小的值  
    41                 return true;
    42             visited[i]=0;
    43             if(now==0)
    44                 return false;
    45         }
    46     }
    47     return false;
    48 }
    49 int main()
    50 {
    51     while(scanf("%d",&n) == 1 && n)
    52     {
    53         int i;
    54         for(i=sum=0;i<n;i++)
    55         {
    56             scanf("%d",&a[i]);
    57             sum+=a[i];
    58         }
    59         sort(a,a+n,cmp);
    60         for(i=a[0];i<sum;i++)//  开始从最长的假设
    61         {
    62             if(sum%i)   //如果不能整除的话  那一定不是 原始 平均长度
    63                 continue;
    64             memset(visited,0,sizeof(visited));
    65             if(DFS(0,0,0,i))
    66             {
    67                 printf("%d
    ",i);
    68                 break;
    69             }
    70         }
    71         if(i==sum)
    72             printf("%d
    ",sum);
    73     }
    74     return 0;
    75 }
  • 相关阅读:
    ajax--->简单加法小练习
    Django----->Ajax
    Django----->inclusion_tag的使用
    分页插件
    权限--中间件
    Django----->一周后的重温
    Django---->视图(View)
    【转载】chmod命令详解
    【转载】linux ls -l命令详解
    js自定制周期函数
  • 原文地址:https://www.cnblogs.com/A-FM/p/5334822.html
Copyright © 2020-2023  润新知