poj 1011 dfs 加剪枝

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.

Input

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.

Output

The output should contains the smallest possible length of original sticks, one per line.

Sample Input

9
5 2 1 5 2 1 5 2 1
4
1 2 3 4
0

Sample Output

6
5

大致题意:将之前剪完的等长木棒拼接回去,求原来可能最短的长度。

首先先想到现在长度的总和sum一定能整除原来的长度len。即sum/len是整数。

想到选取依次枚举木棒拼回去具有相同的子问题,那么我们可以用dfs(深度优先搜索)。由实现方式可知是排列型dfs。复杂度爆炸。考虑剪枝。

给出AC代码:

//2018/7/15
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
int a[100],v[100],n,len,cnt;
//正在拼第stick根原始木棒(已经拼好了stick-1根)

//第stick根木棒的当前长度为cab

//拼接到第stick根木棒中的上一根小木棍last
bool dfs(int stick,int cab,int last)
{
  if(stick>cnt) return true;
  if(cab == len) return dfs(stick+1,0,1);
  int fail = 0;
  for(int i= last;i<=n;i++)
  {
    if(!v[i]&&cab+a[i]<=len&&fail != a[i]){
      v[i] = 1;
    if(dfs(stick,cab+a[i],i+1)) return true;//AC
      fail = a[i];
      //if(dfs(stick,cab+a[i],i+1)) return true;//AC
      v[i] = 0;
      //if(dfs(stick,cab+a[i],i+1)) return true;//WA
      if(cab == 0||cab+a[i] == len) return false;
    //  if(dfs(stick,cab+a[i],i+1)) return true;//WA
    }
  }
  return false;
 }
int main ()
{
  while(scanf("%d",&n)!=EOF&&n)
  {
    int sum = 0,val = 0;
    for(int i= 1;i<=n;i++)
    {
      scanf("%d",&a[i]);
       sum += a[i];
       val = max(val,a[i]);
    }
    sort(a+1,a+n+1);
    reverse(a+1,a+n+1);//优化一 从大到小排序
    for(len = val;len<=sum;len++)//枚举len
    {
      if(sum%len) continue;
      cnt = sum/len;
      memset(v,0,sizeof(v));
      if(dfs(1,0,1)) break;
    }
    printf("%d\n",len);
  }
  return 0;
}

猜你喜欢

转载自blog.csdn.net/strategist_614/article/details/81069949