搜索—小木棍

小木棍

题目描述

乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过 \(50\)

现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度。

给出每段小木棍的长度,编程帮他找出原始木棍的最小可能长度。

输入格式

第一行是一个整数 \(n\),表示小木棍的个数。
第二行有 \(n\) 个整数,表示各个木棍的长度 \(a_i\)

输出格式

输出一行一个整数表示答案。

样例 #1

样例输入 #1

9
5 2 1 5 2 1 5 2 1

样例输出 #1

6

提示

对于全部测试点,\(1 \leq n \leq 65\)\(1 \leq a_i \leq 50\)

分析

利用贪心从大到小进行拼接,这样可以使得减少不必要的搜索次数,而且先拼长的和先拼短的是等效的。对于每个原始木棍长度,一定是总长度约数。

代码实现

#include <bits/stdc++.h>
using namespace std;
int n;	
int sum = 0;
int a[70];
bool visit[70];
int len;
int k;
bool cmp(int a,int b)
{
    return a>b;
}
// vector<int> v;
// int real_num(int x,int z){
// 	for(int i = 1; i <= x; i++)
// 		if(x%i == 0&&a[0]<=i){v.push_back(i);}
// 	return 0;
// }
bool dfs(int i,int rest,int p)//第i堆还差rest的长度到len,第i堆中刚才选了第p根 
{
    if(i>k)//共k堆 
    {
        return 1;
    }
    int fail=-1; 
    for(int x=p+1;x<n;x++)//从第p根开始选
    if(!visit[x])
    { 
        if(a[x]==a[fail]) continue;//注意continue和return
        if(rest>a[x]) 
        {
            visit[x]=1;
            bool w=dfs(i,rest-a[x],x);
            visit[x]=0;
            if(!w) fail=x;
            if(w) return 1;
        }
        else if(rest==a[x])
        {
            visit[x]=1;
            bool w=dfs(i+1,len,-1);
            visit[x]=0;
            return w;
        }
        if(p==-1)return 0;
    }
    return 0;
}
int main(){
	std::ios::sync_with_stdio(false);
cin.tie(0); 
cout.tie(0);

	cin>>n;

	for(int i = 0;i <n; i++){
		cin>>a[i];sum+=a[i];
	}
	sort(a,a+n,cmp);
	// real_num(sum,a[0]);
	for(len = a[0];len <= sum;len++)
		if(sum%len==0){
		{	
			k = sum/len;
			if(dfs(1,len,-1))
		{cout<<len;break;}
}
}
	return 0;
}
posted @ 2023-08-22 01:50  LongDz  阅读(8)  评论(0)    收藏  举报