题目

源地址:

http://poj.org/problem?id=1011

理解

一开始的想法比较简单,单纯的求和然后找出最短的那根。但是这样的做法有下面的一些问题:第一,最后的棒子的和不能比最短的棒子还短;第二,最后的棒子必须是由给定的棒子合成的。因此只能使用搜索的方法,但是常规的搜索会超时,必须辅以有效的剪枝,以下是参考之后的代码。

代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;

int sticks[64], n, len, num, sum;
bool used[64];
bool end;

bool compare(int a, int b)
{
    return a > b;
}

bool dfs(int cur, int left, int level)
{
    if (left == 0)
    {
        if (level == num - 2)
            return true;
        for (cur = 0; used[cur]; cur++);
        used[cur] = true;
        if (dfs(cur + 1, len - sticks[cur], level + 1))
            return true;
        used[cur] = false;
        return false;
    }
    else
    {
        if (cur >= n - 1)
            return false;
        for (int i = cur; i < n; i++)
        {
            if (used[i])
                continue;
            if ((sticks[i] == sticks[i - 1]) && !used[i - 1])
                continue;
            if (sticks[i] > left)
                continue;
            used[i] = true;
            if (dfs(i, left - sticks[i], level))
                return true;
            used[i] = false;
        }
        return false;
    }
}

int main(int argc, char const *argv[])
{
    while (cin >> n)
    {
        if (n == 0)
            break;
        for (int i = 0; i < n; i++)
        {
            scanf("%d", &sticks[i]);
            sum += sticks[i];
        }
        sort(sticks, sticks + n, compare);
        end = false;
        for (len = sticks[0]; len <= sum / 2; len++)
        {
            if (sum % len == 0)
            {
                used[0] = true;
                num = sum / len;
                if (dfs(0, len - sticks[0], 0))
                {
                    end = true;
                    printf("%d\n", len);
                    break;
                }
                used[0] = false;
            }
        }
        if (!end)
            printf("%d\n", sum);
        memset(used, 0, sizeof(used));
    }
    return 0;
}

更新日志

  • 2014年07月16日 已AC。