蓝桥杯——Sticks(搜索)

题目:
George took sticks of the same length and cut them randomly until all parts became at most 50 units long. Now he wants to return sticks to the original state, but he forgot how many sticks he had originally and how long they were originally. Please help him and design a program which computes the smallest possible original length of those sticks. All lengths expressed in units are integers greater than zero.
输入格式:
The input contains blocks of 2 lines. The first line contains the number of sticks parts after cutting, there are at most 64 sticks. The second line contains the lengths of those parts separated by the space. The last line of the file contains zero.
输出格式:
The output should contains the smallest possible length of original sticks, one per line.

思路: 这道题主要就是要求从n个被随意分割后的小木棒中计算出原先y个同样长度x的木棒。因为可能有很多解,所以他要求你求出这个y的最小可能的值。枚举的思路是最基础也是最容易被使用的方法,不过如何更高效的枚举也需要思考。我们应该从n个小木棒中的最大的一根开始,以所有小木棒的总和sum为终点枚举,即maxi~sum之间。然后在选出任意的x后,判断它是否能被总长度整除,若不能,说明不能还原,直接跳过再选择下一个。若可以,则说明有可能可以还原,用dfs深度搜索一下判断。此时的搜索为了避免不必要的时间消耗,需要用剪枝的方法,例如他们都从大到小排序好了,此时选择的小木棒a[i]等于上一个a[i-1],然而上一个小木棒book[i]没有标记,也就是没有选择,那么它也不用继续搜索了,直接可以跳过。
代码如下:

#include <iostream>
#include <algorithm>
#include <string.h>
using namespace std;
int n,x,flag,a[101],book[101];
void dfs(int deep,int len,int dex)
{
    
    
 int i;
 if(len==0)
 {
    
    
  i=1;
  while(book[i])
  i++;
  book[i]=1;
  dfs(deep+1,len+a[i],i+1);
  book[i]=0;
  return;    //及时返回,避免不不必要的搜索
 }
 if(len==x)
 {
    
    
  if(deep==n)
  {
    
    
   flag=1;
  }
  else {
    
    
   dfs(deep,0,1);
  }
  return;
 }
 for(i=dex;i<=n;i++)
 {
    
    
  if(book[i])
  continue;
  if(len+a[i]<=x)
  {
    
    
   if(a[i]==a[i-1]&&book[i-1]==0)
   continue;
   book[i]=1;
   dfs(deep+1,len+a[i],i+1);
   book[i]=0;
   if(flag)
   return;
   if(len+a[i]==x)
   return;
  }
 }
 return;
}
bool cmp(int a,int b)
{
    
    return a>b;}
int main()
{
    
    
 int i,sum;
 while(cin>>n||n)
 {
    
    
  sum=0;
  for(i=1;i<=n;i++)
  {
    
    
   cin>>a[i];
   sum+=a[i];
  }
  sort(a+1,a+n+1,cmp);
  for(i=a[1];i<=sum;i++)
  {
    
    
   if(sum%i)
   continue;
   x=i;
   memset(book,0,sizeof(book));
   flag=0;
   dfs(0,0,1);
   if(flag)
   {
    
    
    cout<<i<<endl;
    break;
   }
  }
 }
 return 0;
}

输入样例:
9
5 2 1 5 2 1 5 2 1
4
1 2 3 4
0
输出样例:
6
5

猜你喜欢

转载自blog.csdn.net/HT24k/article/details/106991974