POJ 1011 搜索剪枝

来源:互联网 发布:肯塔基大学 知乎 编辑:程序博客网 时间:2024/06/04 23:36

 

 

如题:http://poj.org/problem?id=1011 

 

             题目要求

                 输入:小木棒的数量n,以及每个小木棒的长度

                 输出:这些小木棒可以拼成若干根等长木棍,求拼成木棍的最小长度

                

                 1.拼成后木棍可能的长度为所有输入中最长的一直到所有输入长度之和(对这些小木棍长度降序排列)

                 2.深搜,DFS(int  len,int remains_len,int n)第一个参数尝试去拼成木棍的长度,第二个参数木棍剩下的长度,第三个还有多少个小木棍可以去拼剩下的

                3.剪枝,第一,若尝试用第i根小木棍拼失败,那么长度和第i根小木棍一样的都会失败,第二,如果第i根小木棍长度正好等于remains_len,但是没有成功,那么之后的小木棍都不可能成功,因为小木棍为降序,这么适合的一根不能成功,后面更不可能成功,第三,若尝试过后,len=remains_len,说明又进行一轮新的拼接,子问题不能完成所有任务,  那么整体不可能完成任务

#include<iostream>
#include<algorithm>
using namespace std;


int len[68]; //小木棍的长度
int visited[68]; //小木棍是否被访问过
int N;
int cmp(const void * a,const void * b)  

{
 return *(int *)b-*(int *)a; 
}

int DFS(int s_len,int remains_len,int n)
{
 if(remains_len==0&&n==0)
  return s_len;
 if(remains_len==0)
  remains_len=s_len;
 for(int i=1;i<=N;i++)
 {
  if(visited[i]==1)
   continue;
  if(remains_len>=len[i])
  {
  visited[i]=1;
  if(DFS(s_len,remains_len-len[i],n-1))
   return s_len;
  visited[i]=0;
  if(len[i]==remains_len||s_len==remains_len)
   break;
  while(len[i]==len[i+1])
   i++;
  }
 }
 return 0;
}


int main()
{
 int sma_len,k,sum; //小木棍数量
 while(scanf("%d",&N)&&N)
 {
  int i;
  sum=0;
  for(i=1;i<=N;i++)
  {
   scanf("%d",&len[i]); //输入每一根小木棍的长度
   sum+=len[i];
  }
  qsort(len+1,N,sizeof(int),cmp); //降序排列小木棍长度
  for(sma_len=len[1];sma_len<=sum;sma_len++)
  {
   memset(visited,0,sizeof(visited));
   if(sum%sma_len==0) //拼成x根长度相同的小木棍sma_len,所以sma_len*x=sum;
   {
    k=DFS(sma_len,sma_len,N);
     if(k)
     break;
   }
  }
  cout<<k<<endl;
 }
 return 0;
}

 

0 0