poj 1011

来源:互联网 发布:windows 添加路由 编辑:程序博客网 时间:2024/06/16 06:42
#include<iostream>#include<cstring>#include<algorithm>#include<cstdio>using namespace std;int n,st[64+10],ans,sum,num,l;//l代表当前需要判断的组合木棍长度 bool s[64+10];//记录次木棍是否被访问过 bool cmp(int a,int b){    return a>b;}bool dfs(int len,int k,int cnt){//len代表正在合并的木棍已有的长度;k代表当前搜索的木棍的下标;cnt记录合并好的木棍个数     if(cnt==num)//如果已经合并完成,返回即可        return true;    if(len==l)//如果木棍已合并好,搜索下一根        return dfs(0,1,cnt+1);    bool flag=false;//记录是否有合法情况     for(int i=k;i<=n;i++){        if(st[i]==st[i-1]&&!s[i-1])//如果当前与木棍长度相同的木棍已被搜索过并且无法满足,那么此木棍必定不可能             continue;        else if(!s[i]&&len+st[i]<=l){            s[i]=true;            if(dfs(len+st[i],i+1,cnt)){//如果满足                flag=true;                break;            }            s[i]=false;//回溯             if(k==1)//如果当前需要判断的木棍是第一根木棍那么此时len=0,若是从第一根木棍开始搜索且无法完成组合木棍,那么就没有必要再搜了                 return false;        }    }    if(!flag)        return false;    return true; }int main(){    while(scanf("%d",&n)&&n!=0){        sum=0;        memset(st,0,sizeof(st));        for(int i=1;i<=n;i++){            scanf("%d",&st[i]);            sum+=st[i];        }        sort(st+1,st+n+1,cmp);//组合木棍长度最小不会小于最长小木棍长度        for(l=st[1];l<=sum/2;l++){//剪枝1:组合木棍最大长度,不会大于总和的一半            if(sum%l==0){//剪枝2:如果总长度无法均分为长度为l的木棍,则不可能                 num=sum/l;//num记录组合木棍的个数                 memset(s,false,sizeof(s)); //s[i]=false代表第i个木棍未被用过                if(dfs(0,1,0))                    break;            }        }        if(l>sum/2)//一根木棍             printf("%d\n",sum);        else            printf("%d\n",l);    }    return 0;}
0 0