PKU 1011 Sticks

/*
据说是经典深搜剪枝题, 我感觉也没有比较隐蔽的需要剪枝的地方
其实平时coding的时候我们已经潜意识优化了很多东西, 自己也不一定察觉
好的习惯蛮有用的
*/

#include 
< iostream >
#include 
< algorithm >
#define  MAXN 64
using   namespace  std;

int  N, LEN, M;    // LEN为原始棍子长度, M为原始棍子数量 
int  S[MAXN], MK[MAXN];
bool  FLAG;
 
int  cmp( int  a,  int  b)
{
    
return  a  >  b;
}

void  dfs( int  k,  int  sum,  int  cnt)
{
    
if  (cnt  ==  M)
        FLAG 
=   true ;
    
else   if  (sum  ==  LEN)
        dfs(
0 0 , cnt + 1 );
    
else
        
for  ( int  pre  =   - 1 , i  =  k; i  <  N; i ++ )
            
if  ( ! MK[i]  &&  S[i] != pre  &&  S[i] + sum <= LEN)
            {
                pre 
=  S[i];
                MK[i] 
=   true ;
                dfs(i
+ 1 , sum + S[i], cnt);
                MK[i] 
=   false ;
                
if  (k  ==   0   ||  FLAG)
                    
return ;
            }
}

int  main()
{
    
int  sum, i;
    
    
while  (scanf( " %d " & N)  !=  EOF  &&  N)
    {
        FLAG 
=   false ;
        sum 
=   0 ;
        
for  (i  =   0 ; i  <  N; i ++ )
        {
            scanf(
" %d " & S[i]);
            sum 
+=  S[i];
        }
        sort(S, S
+ N, cmp);
        
        
for  (LEN  =  S[ 0 ]; LEN  <  sum; LEN ++ )
            
if  (sum  %  LEN  ==   0 )
            {
                M 
=  sum  /  LEN;
                memset(MK, 
0 sizeof (MK));
                dfs(
0 0 0 );
                
if  (FLAG)
                    
break ;
            }
        printf(
" %d\n " , FLAG ?  LEN : sum);
   }
   
return   0 ;
}

转载于:https://www.cnblogs.com/lotus3x/archive/2008/07/25/1251552.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值