nyoj 293 Sticks

Sticks

时间限制:3000 ms  |  内存限制:65535 KB

难度:5

描述

George took sticks of the same length and cut them randomly until all parts became at most 50 units long. Now he wants to return sticks to the original state, but he forgot how many sticks he had originally and how long they were originally. Please help him and design a program which computes the smallest possible original length of those sticks. All lengths expressed in units are integers greater than zero.

输入

The input contains blocks of 2 lines. The first line contains the number of sticks parts after cutting, there are at most 64 sticks. The second line contains the lengths of those parts separated by the space. The last line of the file contains zero.

输出

The output should contains the smallest possible length of original sticks, one per line.

样例输入

9

5 2 1 5 2 1 5 2 1

4

1 2 3 4

0

样例输出

6

5

#include <string.h>
#include <stdio.h>
#include <algorithm>

using namespace std;
int sticks[65],n,sum,num,l;//l:最长的木棒的长度   num:圆木棒的个数    sum:圆木棒的总长度
bool mark[65];
bool cmp(int a,int b)
{
    return a>b;
}

//s:已经组成的小木棒的个数,le:当前搜索时正在组成的小木条的长度。pos:要组合的小木条的下标位置
bool dfs(int s,int le,int pos)
{
    int i;
    bool sign = (le == 0?true:false);
    if(s==num)return true;
    for(i = pos + 1;i < n;i++)
    {
        if(mark[i])continue;//如果这个小木棒组合过则从下一个开始
        if(le + sticks[i]==l)//如果组合刚好组成l长度的木棒那么就要组合下一根木棒了即第s+1根
        {
            mark[i] = true;
            if(dfs(s+1,0,-1))//第s根已经组合成功了组合下一根
            return true;
            mark[i] = false;
            return false;//如果组合失败了那么就要返回false 而且这个木棒的状态应还原为没组合过
        }
        else if(le + sticks[i]<l)
        //如果组合当前这根后长度仍然小于l那么从i开始往下找继续组合第S根木棒
        {
            mark[i] = true;
            if(dfs(s,le+sticks[i],i))//如果可以组成就返回true
            return true;
            mark[i] = false;
            if(sign)return false;
            while(sticks[i]==sticks[i+1])i++;
        }
    }
    return false;
}

int main()
{
    while(scanf("%d",&n)!=EOF,n)
    {
        sum = 0;

        for(int i = 0; i < n; i++)
        {
            scanf("%d",&sticks[i]);
            sum += sticks[i];
        }
        sort(sticks,sticks+n,cmp);//将木棒从大到小排序
        for(l = sticks[0]; l <= sum; l++)//从最大的开始搜索
        {
            if(sum%l==0)//如果该长度可以被整除那么可能是结果,否则继续
            {
                num = sum/l;//num:记录该情况下可以组成的木棒的数目。
                memset(mark,false,sizeof(mark));//每种情况都要进行初始化,把所有的木棒的使用状态设为false
                if(dfs(1,0,-1))//当返回true时说明搜索成功了,可以组成该长度木条
                {
                    printf("%d
",l);
                    break;
                }
            }
        }
    }
    return 0;
}      

  

原文地址:https://www.cnblogs.com/zhangliu/p/7053030.html