uva307 dfs

来源:互联网 发布:高中生电脑编程培训 编辑:程序博客网 时间:2024/04/28 04:10

把博客当作一个记录代码的地方吧。这个题想一想还真的挺不错的,能提高对回溯法的理解。题意不难理解,一堆切开的小木棒,然后把这些小木棒合起来,找到这些合起来的小木棒的最小长度,最关键的一点这些小木棒合起来的长度都是一样的。

我开始的思路试枚举多少根小木棒,然后通过总的除以根数就得到了小木棒的长度,然后一一去判断,结果写着写着怎么也不会写了,就从网上借鉴了大神们的代码。思路:直接枚举长度,然后通过递归求根数然后判断相乘之后能否等于总长度即可,这里要注意的就是枚举的长度一定要大于等于木棒的最大长度,小于等于总长度。网上的大神貌似都用到了剪枝,但我觉得剪不剪都一样(可能是自己太弱了,看不出区别)所以就没有用到剪枝。不多说,上代码:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxed=100+10;int panDuan[maxed],n,muBang[maxed],changDu,zong;int main(){    bool slove(int,int,int);    bool cmp(int,int);    while(scanf("%d",&n)!=EOF&&n){        //memset(panDuan,0,sizeof(panDuan));        memset(muBang,0,sizeof(muBang));        int t;        zong=0;        for(int i=0;i<n;i++){            scanf("%d",&t);            muBang[i]=t;            zong+=t;        }        sort(muBang,muBang+n,cmp);//对木棒长度进行排序,这样每次都从最大的开始找,会节省很多时间。        for(changDu=muBang[0];changDu<=zong;changDu++)            if(!(zong%changDu)){                //cout<<2<<endl;                memset(panDuan,0,sizeof(panDuan));                if(slove(0,0,0))                    break;            }        printf("%d\n",changDu);    }    return 0;}bool cmp(int x,int y){    return x>y;}bool slove(int now,int geShu,int cur)//now当前长度,geShu当前的木棒根数,cur当前枚举到的位置(这里一定要写位置,如果每次都从0开始枚举会出现时间溢出){    //cout<<1<<endl;    if(geShu*changDu==zong)        return true;    for(int i=cur;i<n;i++){        if(panDuan[i])            continue;//        if(i&&!panDuan[i-1]&&muBang[i]==muBang[i-1])//            continue;        if(now+muBang[i]==changDu){            panDuan[i]=1;            if(slove(0,geShu+1,0))                return true;            panDuan[i]=0;            return false;        }        else if(now+muBang[i]<changDu){            panDuan[i]=1;            if(slove(now+muBang[i],geShu,i+1))                return true;            panDuan[i]=0;            if(now==0)                return false;        }    }    return false;}

0 0
原创粉丝点击