搜索—小木棍
小木棍
题目描述
乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过 \(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;
}

浙公网安备 33010602011771号