其他分享
首页 > 其他分享> > 搜索:小木棍

搜索:小木棍

作者:互联网

题目链接:https://ac.nowcoder.com/acm/problem/50243

题目描述


乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50。现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度。给出每段小木棍的长度,编程帮他找出原始木棍的最小可能长度。

输入描述


第一行为一个单独的整数N表示砍过以后的小木棍的总数。第二行为N个用空格隔开的正整数,表示N根小木棍的长度。 1≤N≤60

输出描述


输出仅一行,表示要求的原始木棍的最小可能长度。

示例


输入

9
5 2 1 5 2 1 5 2 1

输出

6

分析


本题采用深搜加剪枝的算法。
首先,N个小木棍的长度均为整数,因此原长度必为整数(若原长为小数,则进行分割必产生小数长度的木棍)。
题目要求找出可能的最小木棒长度,所以我们可以想到通过深搜一个数一个数的去验证,但显然单纯深搜会相当耗时,最多有
60个木棍,不优化的话每确定一个木棍都要遍历60次,总共确定60次,且仅仅完成一个长度的试探。
因此,我们就要通过一些优化技巧和剪枝来提高效率。
优化技巧:

剪枝:

以上各方面实现到位,即可AC。

AC代码


#include <iostream>
#include <algorithm>
#include <cstring>
#include <functional>
using namespace std;
int N;
int a[60];      //存木棍长度
bool visited[60];
bool dfs(int num, int len, int res, int now) //剩余多少木棍 假设的木棍长度 
{                                            //当前正拼接木棍的长度 下一层递归的起始搜索序号
    if (res == 0 && num == 0)
        return true;
    if (res == 0)
    {
        res = len;
        now = 0;
    }
    for (int i = now; i < N; i++)
    {
        if (visited[i])
            continue;
        if (a[i] > res)
            continue;
        visited[i] = true;
        if (dfs(num - 1, len, res - a[i], i + 1))
            return true;

        visited[i] = false;
        if (a[i] == res || res == len)  //分别表示木棒尾端 和木棒头部拼接失败
            return false;
        while (a[i] == a[i + 1])        //越过长度相同的木棍
            i++;
    }
    return false;
}
int main()
{
    int sum = 0;
    cin >> N;
    for (int i = 0; i < N; i++)
    {
        cin >> a[i];
        sum += a[i];
    }
    sort(a, a + N, greater<int>());
    for (int i = a[0]; i <= sum; i++)
    {
        if (sum % i == 0 && dfs(N, i, i, 0))
        {
            cout << i << endl;
            break;
        }
    }
    return 0;
}

标签:int,res,木棒,搜索,木棍,长度,试探
来源: https://www.cnblogs.com/kongaobo/p/14551293.html