poj 1011 dfs

题意:输入n,和n根小木棒的长度。已知n根小木棒是由若干根长度相同的原棒分解而来。求原棒可能的最小长度。
此题号称是DFS入门的神题,卡了好久,在群里讨论听说这种剪枝是A*剪枝,有时间研究下...
我感觉这个代码比较神,我也是看完他的代码才AC的。
其它剪枝就不说了,主要说明下两个比较强力的剪枝。
剪枝1:当连续的小木棒长度相同,并且前一根木棒没有被标记,也就是搜索失败了,那么下一根长度相同的木棒也不用搜索了。
剪枝2:如果又重新搜索到第一根木棒的话,意味着第一根木棒没有拼接成功,那么就不用再往下搜索了,因为这根木棒直到最后也不会拼接成功。
#include<iostream>
#include<algorithm>
#define max 65
using namespace std;

int cmp(int a,int b)
{
    return a>b;
}

int a[max],n,len,vis[max],flag,num,pre;

void dfs(int i,int s,int edge)
{
    int j;
    if(flag) return;
    if(edge==num) {flag=1;return;}
    for(j=i;j<n;j++)
    {
     if(s+a[j]<=len&&!vis[j])
     {
       if(!vis[j-1]&&a[j-1]==a[j]) continue;//强力剪枝1 
       vis[j]=1;               
       if(s+a[j]==len)
       dfs(0,0,edge+1);
       if(s+a[j]<len)
       dfs(j+1,s+a[j],edge);
       vis[j]=0;
       if(i==0) return ;//强力剪枝2 
     }
    }
}
int main()
{
    int i,sum;
    while(scanf("%d",&n)&&n)
    {
      sum=0;
      for(i=0;i<n;i++)
      {
        scanf("%d",&a[i]);
        sum+=a[i];
      }
      sort(a,a+n,cmp);
      memset(vis,0,sizeof(vis));
      flag=0;
      for(len=a[0];len<=sum;len++)
      {
         if(sum%len==0)
         {
           num=sum/len;
           dfs(0,0,0);
           if(flag) break;
         }
      }
      printf("%d\n",len);
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值