POJ 1011 Sticks

Posted 念你成疾

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 1011 Sticks相关的知识,希望对你有一定的参考价值。

Description

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.

Input

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.

Output

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

Sample Input

9
5 2 1 5 2 1 5 2 1
4
1 2 3 4
0

Sample Output

6
5

Source

 
    题目大致意思:就是有一个人把几根木头切成了几段,然后现在他想复原这些木棒,但是他又不记得原来有几根木棒了。求原来木棒的最小长度。
    一道典型的DFS题目,而且要不停的剪枝。
    1. 所有的木棒都要用到
    2.所有木棒的长度可以整除最短的长度
    3.最短的长度至少是分成几段里面的最长的长度
    4.如果现在选中的一根木棒和上一次选中的木棒一样长,但是上一根木棒没有被采用,那么这一根也绝对不会被采用,因为这些木棒只有长度的差异,现在长度都一样了,那么就可以看做两个木棒完全等价,既然上一根都没有被采用,与它等价的又怎么可能会被采用呢?
    5.如果进行一次搜索以后假定木棒的剩余长度都没有任何改变(我们用假定木棒的最小长度减枚举的木棒),那么这是绝对不正常的情况,因为上面说了,木棒的最小长度应该是切断木棒里的最长的长度,也就是说Len>=Stick         (Len是假定的最短木棒长度,Stick是任意切断的木棒长度),如果出现这种情况,那么我们假定的最小长度失效
    6.如果选用的被切断的木棒长度和剩余的长度一样,但是最后还是匹配失败了,那么这个最短长度也不是正确的,直接返回false
 
代码如下:
#include <iostream>

using namespace std;

int used[100];             //判断第i根木棒是否被采用
int stick[100];            //记录第i根木棒的长度

void quicksort(int left, int right)                             
{
    int i, j, temp;
    if (left < right)
    {
        i = left, j = right, temp = stick[i];
        while (i < j)
        {
            while (i < j&&stick[j] <= temp) j--;
            stick[i] = stick[j];
            while (i < j&&stick[i] >= temp) i++;
            stick[j] = stick[j];
        }
        stick[i] = temp;
        quicksort(left, j - 1);
        quicksort(j + 1, right);
    }
}

int DFS(int Len, int left, int len, int n)     //Len 每根木棒的长度  left 剩余的木棒
{
    if (len == 0 && left == 0) return 1;
    if (len == 0) len = Len;
    for (int i = 0; i < n; i++)
    {
        if (!used[i] && stick[i] <= len)
        {
            if (i > 0 && stick[i] == stick[i - 1] && !used[i]) continue;      //前面有一根和目前这根一样长的但是没有被采用 那么这根也不会被采用 第二次剪枝
            used[i] = 1;
            if (DFS(Len, left - 1, len - stick[i], n)) return 1;
            else
            {
                used[i] = 0;
                if (stick[i] == len || len == Len) return 0;
                //如果这根木棒和剩余长度一样或者剩余木棒长度没有改变 那么绝对不会成功
                //因为 如果选中的木棒和剩余的一样长却匹配失败 那么后面的木棒是没有希望的
                //如果木棒的长度都没有改变 那假设的长度绝对不会成立的
                //第三次剪枝
            }
        }
    }
}

int main()
{
    int n, len, sum;
    while (cin >> n)
    {
        sum = 0;                                    //所有木棒的长度和
        for (int i = 0; i < n; i++)
            cin >> stick[i], sum += stick[i];
        memset(used, 0, sizeof(used));
        quicksort(0, n - 1);                        //从大到小排列 由于每根木棒都要用到,所以从最大的一根开始,这样可以减少递归次数
        len = stick[0];                             //木棒最小长度应该是给出的木棒的最大长度
        while (1)
        {
            if (sum%len == 0)                       //给出的木棒的总长度一定可以整除单根木棒的长度    第一次剪枝
                if (DFS(len, n, len, n)) break;
            len++;                                  //枚举木棒的长度
            memset(used, 0, sizeof(used));
        }
        cout << len << endl;
    }
}

 

 

以上是关于POJ 1011 Sticks的主要内容,如果未能解决你的问题,请参考以下文章

POJ#1011 Sticks

POJ 1011 Sticks DFS 剪枝

poj-1011 sticks(搜索题)

POJ 1011 Sticks

poj 1011 Sticks

POJ 1011 Sticks