POJ 1011--Sticks

题意

题目的大意呢是说有一堆长短不一的小棍,它们由原来若干根长度相同木棍截断而成,要求原来木棍的最短长度。

分析

这是一道比较典型的深度搜索题,原来的木棍长度最小可能是当前小棍里的最长值,所以先对小棍进行从大到小的排序, max(s1,s2,s3…sn) <= 原长度 <= sum(s1,s2,s3…sn)。
这里面要注意的是不要对相同长度的小棍进行重复搜索,那样必定超时。
这里采用了一个结构体,里面记录了下一个长度不同的小棍位置,这样得以减小搜索量。
代码如下:
Memory: 232K Time: 32MS Length:80LINES

#include
#include
using namespace std;
struct  Stick
{
    int Length;
    bool IsUsed;
    int Next;
};
bool Compare(const Stick&s1, const Stick&s2) { return s1.Length > s2.Length; }; //从大到小排序
void Construct(Stick* StickArray, const int& Count)                //计算下一个长度不同的位置
{
    for (int i = 0; i < Count; ++i)
    {
        for (int j = i + 1; j < Count; ++j)
        {
            if (StickArray[i].Length != StickArray[j].Length)
                for (; i < j; ++i)  StickArray[i].Next = j;
        }
        StickArray[i].Next = Count;
    }
};
int NextNotUsed(const Stick* StickArray, int Current, const int& Count) //找到下一个还未选取的小棍
{
    while (Current < Count&&StickArray[Current].IsUsed)     ++Current;
    return Current;
}
int RemSum(const Stick* StickArray, const int& Count, int Start)//计算从当前位置开始的剩余小棍长度和
{
    int Sum = 0;
    for (; Start < Count; Start = NextNotUsed(StickArray, Start + 1, Count))
        Sum += StickArray[Start].Length;
    return Sum;
}
bool RecurSearch(Stick* StickArray, int Remain, const int& Count, int RemLength, const int& AssumeLength, int FirNotUsed)
{
    if (Remain == 0 && RemLength == 0)  return true; //选取完成
    if (RemLength == 0)                                  //假定的一根原木棍已经匹配完,再次赋值接着搜索
    {
        RemLength = AssumeLength;
        FirNotUsed = NextNotUsed(StickArray, 0, Count);
    }
    for (int i = FirNotUsed; i < Count; i = NextNotUsed(StickArray, StickArray[i].Next, Count))
    {
        if (RemLength > RemSum(StickArray, Count, i))   return false; //已经大于后面未选取的小棍和
        if (RemLength >= StickArray[i].Length)
        {
            StickArray[i].IsUsed = true;
            if (RecurSearch(StickArray, Remain - 1, Count, RemLength - StickArray[i].Length, AssumeLength, NextNotUsed(StickArray, i, Count)))  return true;
            StickArray[i].IsUsed = false;
            if (RemLength == AssumeLength || RemLength == StickArray[i].Length)     return false; //已经失败,不用接着搜索
        }
    }
    return false;
};
int Calculate(Stick* StickArray, const int& Count, const int& Sum)
{
    int AssumeLength = StickArray[0].Length;
    for (; AssumeLength != Sum; ++AssumeLength)
        if (Sum%AssumeLength == 0 && RecurSearch(StickArray, Count, Count, AssumeLength, AssumeLength, 0))  break;
    return AssumeLength;
};
int main()
{
    int Count = 0;
    while (cin >> Count&&Count != 0)
    {
        Stick StickArray[64];
        int Sum = 0;
        for (int i = 0; i < Count; ++i)
        {
            cin >> StickArray[i].Length;
            Sum += StickArray[i].Length;
            StickArray[i].IsUsed = false;
        }
        stable_sort(StickArray, StickArray + Count, Compare);
        Construct(StickArray, Count);
        cout << Calculate(StickArray, Count, Sum) << endl;
    }
    return 0;
}

你可能感兴趣的:(C++/C,POJ解题报告)