2817:木棒 【递归+剪枝】

来源:互联网 发布:电脑usb001端口是哪个 编辑:程序博客网 时间:2024/04/27 11:33

乔治拿来一组等长的木棒,将它们随机地裁断,使得每一节木棍的长度都不超过50个长度单位。然后他又想把这些木棍恢复到为裁截前的状态,但忘记了初始时有多少木棒以及木棒的初始长度。请你设计一个程序,帮助乔治计算木棒的可能最小长度。每一节木棍的长度都用大于零的整数表示。

Input 

输入包含多组数据,每组数据包括两行。第一行是一个不超过64的整数,表示砍断之后共有多少节木棍。第二行是截断以后,所得到的各节木棍的长度。在最后一组数据之后,是一个零。

Output 

为每组数据,分别输出原始木棒的可能最小长度,每组数据占一行。

Sample Input 

9

5 2 1 5 2 1 5 2 1

4

1 2 3 4

0

Sample Output 

6

5

////  main.cpp//  木棒////  Created by JUNJIEGAO on 15/11/6.//  Copyright © 2015?? JUNJIEGAO. All rights reserved.//安师大OJ上此题比较坑……北大百炼10ms通过 安师大OJ过不了……//修改后北大百炼0ms通过#include <iostream>#include <cstdio>#include <algorithm>#include <string.h>#include <time.h>using namespace std;int n;int len;int sum;int list[65];int getsite[65];int way[64];int step;int cmp (int a,int b){    return a>b ? 1:0;}int rec (int stick,int overall,int j){    int i;    if (overall==sum)        return 1;    if (stick==len)    {        stick = 0;        j = 0;    }        for (i=j+1;i<n;i++)    {        if (getsite[i]==1 || stick+list[i]>len)            continue;        getsite[i] = 1;        way[step] = i;        step++;        if(rec(stick+list[i],overall+list[i],i))            return 1;        step--;        getsite[i] = 0;        while (list[i+1]==list[i])//关键剪枝:若发现选择第i个木棒不能组合 则跳过与i值相同的木棒        {            i++;        }        if (stick==0 || stick+list[i]==len) break;//剪枝:如果第一次选择木棒就不能组合 则直接跳出本次长度的猜测 如果正好可以拼成猜测的长度 依然组合失败 则判定此次猜测也是错的 直接跳出    }    return 0;}int main(int argc, const char * argv[]) {    int i;    int Max;   // clock_t start,end;    while (scanf("%d",&n))    {        memset(getsite, 0, sizeof(getsite));        sum = 0;        Max = 0;        step = 0;        if (n==0)        {            return 0;        }        for (i=0;i<n;i++)        {            scanf("%d",&list[i]);            Max = Max > list[i] ? Max:list[i];            sum+=list[i];        }       // start = clock();        sort(list,list+n,cmp);        for (len=Max;len<=sum;len++)        {            if (sum%len!=0)            {                continue;            }            if (rec(0, 0, -1))            {                cout<<len<<endl;                break;            }        }       // end = clock();       // cout<<end-start<<endl;    }    return 0;}


0 0