zoukankan      html  css  js  c++  java
  • uva 307 Sticks

    刚开始在poj过了,拿到uva居然超时。改了好久都没成功,最后问了一个同学,稍微改了一下思路才ac。给uva数据跪了,电费不要钱吗?


    这题数据太恶心,所以必需剪枝。


    1.将数据从大到小排序,方便后面选择和操作。

    2.最后答案只能是sum的约数,所以枚举范围最小为最长的那个棍子的长度,最大只需要到sum/2,如果前面没有求出答案,那么就是sum了。

    3.在深搜过程中,如果当前棍子没有用上,下一个棍子如果长度一样,不用再试。

    4.各种异常情况返回。

    #include "stdio.h"
    #include "string.h"
    #include "algorithm"
    using namespace std;
    
    int a[70],u[70],ans,n,s;
    bool flag;
    
    bool cmp(int x,int y)
    {
        return x>y;
    }
    
    void dfs(int num,int st,int len)
    {
        int i;
        if(num==s) {flag=1;return;}
        if(flag) return;
        for(i=st;i<n;i++)
        {
            if(!u[i])
            {
                u[i]=1;
                if(a[i]+len<ans) dfs(num,i+1,a[i]+len);
                else if(a[i]+len==ans) dfs(num+1,0,0);
                u[i]=0;//恢复现场
                if(!st||a[i]==ans||a[i]+len==ans) return;//4对各种可以继续搜索下去的,却反回了的剪枝。没有这一步会超时
                while(a[i+1]==a[i]) i++;//3中剪枝
            }
        }
        return ;
    }
    
    int main()
    {
        int i,sum;
        while(~scanf("%d",&n))
        {
            if(n==0) break;
            sum=0,flag=0;
            for(i=0; i<n; i++)
            {
                scanf("%d",&a[i]);
                sum+=a[i];
            }
            sort(a,a+n,cmp);//从大到小排序
            for(ans=a[0];ans<=sum/2; ans++)
            {
                if(sum%ans==0)
                {
                    s=sum/ans;
                    memset(u,0,sizeof(u));
                    dfs(0,0,0);
                    if(flag==1) break;
                }
            }
            if(ans>sum/2) printf("%d
    ",sum);
            else printf("%d
    ",ans);
        }
        return 0;
    }


    poj ac代码

    #include "stdio.h"
    #include "string.h"
    #include "algorithm"
    using namespace std;
    
    int a[70],u[70],ans,n;
    
    bool cmp(int x,int y)//sort排序用的
    {
        return x>y;
    }
    
    bool dfs(int num,int len,int st)
    {
        if(num==n) return 1;//全部的棒子都实用了
        else if(len==ans) return dfs(num,0,0);
        else
        {
            int i,t;//t记录ai-1,剪枝,如果相等的棒子第一个没用,后面也不去用
            for(t=0,i=st;i<n;i++)
                if(!u[i]&&len+a[i]<=ans&&t!=a[i])//可以使用
                {
                    t=a[i],u[i]=1;
                    if(dfs(num+1,len+a[i],i+1)) break;
                    u[i]=0;//恢复现场
                    if(st==0) return 0;//如果遍历了一遍后,为找到ai,当前ans错误,返回
                }
                if(n==i) return 0;//如果遍历了一遍后,为找到ai,当前ans错误,返回
                else return 1;
        }
    }
    
    int main()
    {
        int i,sum;
        while(~scanf("%d",&n))
        {
            if(n==0) break;
            sum=0;
            for(i=0; i<n; i++)
            {
                scanf("%d",&a[i]);
                sum+=a[i];
            }
            sort(a,a+n,cmp);//从大到小排序
    
            //从最长的棒子开始遍历,最大为sum
            for(ans=a[0]; ans<sum; ans++)
            {
                if(sum%ans==0)//ans肯定能被sum整除
                {
                    memset(u,0,sizeof(u));//数组清零,0为未用,1为已用
                    if(dfs(0,0,0))
                    break;
                }
            }
            printf("%d
    ",ans);
        }
        return 0;
    }



    版权声明:本文为博主原创文章,未经博主允许不得转载。http://xiang578.top/

  • 相关阅读:
    项目中docker swarm实践
    Spring的分模块开发的配置
    单点登录
    在服务器搭建git服务器
    Learn Git Lesson06
    kafka Poll轮询机制与消费者组的重平衡分区策略剖析
    gulp初体验
    vue-cli3中axios如何跨域请求以及axios封装
    vue-cli3中怎么配置vue.config.js文件
    svn的下载与安装,使用,包教包会!!!
  • 原文地址:https://www.cnblogs.com/xryz/p/4848114.html
Copyright © 2011-2022 走看看