UVA-307 Sticks (搜索剪枝)

Description

Download as PDF

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 file contains blocks of 2 lines. The first line contains the number of sticks parts after cutting. The second line contains the lengths of those parts separated by the space. The last line of the file contains zero.

Output

The output file 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
此題的大致意思就是,給你n跟木棒,讓你拼成木棍(木棒-->木棍 ,它倆是有區別滴~~)要儘可能的拼多的木棍,也就是計算拼的木棍的最短長度。

把數據按降序排列,從最大的開始判斷,一直判斷到所有數據和的一半,如果都拼不成功,那麼只能拼成一根嘍!

四次剪枝:

1、不要在同一位置嘗試同一根木棒,即如果某根木棒拼不成功,那麼跟它相同的木棒都不用繼續判斷直接跳過。

    假如  5  5  4  4 3  要拼長度爲6的木棍是 用5拼不可能成功,那個第二個長度爲5的木棒就不用判斷了。

2、如果由於以後的拼接失敗,需要重新調整第i根棍子的拼法,則不會考慮替換第i根棍子中的第一根木棒(換了也沒用)。why?

     因爲假設替換後能全部拼成功,那麼這被換下來的第一根木棒,必然會出現在以後拼好的某根棍子k中。

3、不要希望通過僅僅替換已拼好棍子的最後一根木棒就能夠改變失敗的局面。

     因爲把已拼好棍子的最後一根木棒替換下來,那麼肯定有一個或者兩個或者更多拼在一起是最後一根木棒的長度,把它放在後面就好了! 幹嘛要替換人家最後一根木棒呢。

4、每次找一根木棒的時候,只要這不是一根棍子的第一條木棒,就不應該從下標爲0的木棒開始找,而應該從剛剛(最近)接上去的那條木棒的下一條開始找。

    因爲按降序排列的麼,上面的都不行,肯定只判斷下面的嘍!

代碼如下

#include<iostream>
#include<cstdio>
#include<map>
#include<math.h>
#include<cstring>
#include<algorithm>
using namespace std;

int tused[100], tlength[100], s, m, n;

bool cmp(int A, int B)
{
    return A > B;
}

int Dfs(int M, int L, int pos)
{
    if(M == 0 && L ==0)
    {
        return 1;
    }
    if(L == 0)
    {
        pos = -1;//剪枝4
        L = m;//如果剛好拼好,接着拼下一根
    }
    for(int i = pos + 1; i < n; i++)
    {
        if(!tused[i] && tlength[i] <= L)
        {
            if(i > 0)
            {
                if((tlength[i - 1] == tlength[i]) && (!tused[i-1]))
                     continue;//剪枝1
            }
            tused[i] = 1;//標記已使用
            if(Dfs(M - 1, L - tlength[i], i))
                return 1;
            else
            {
                tused[i] = 0;
                if(tlength[i] == L || L == m)
                    return 0;//剪枝 2 3
            }
        }
    }
    return 0;
}
int main()
{
    int i, sum;
    while(scanf("%d",&n) && n)
    {
        sum = 0;
        for(i = 0; i < n; i++)
        {
            scanf("%d",&tlength[i]);
            sum += tlength[i];
        }
        sort(tlength, tlength + n, cmp);//按降序排列
        for(m = tlength[0]; m <= sum / 2; m++)
        {
            if(sum % m != 0)
                continue;// 不加這個條件超時鳥~~~~加上100ms以下!
            memset(tused, 0, sizeof(tused));
            if(Dfs(n ,m, -1))//n代表木棒的個數,m爲長度,-1位要訪問的木棒序號
            {
                printf("%d\n",m);
                break;
            }
        }
        if(m > sum / 2)
            printf("%d\n",sum);
    }
    return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章