【~~~】POJ-1011

一个DFS的经典题目,在搜索的过程中,还要不断的进行剪枝的过程,避免不必要的搜索时间的浪费

1.测试的最小棒长度必须是所有棒长的因数。//sum%currentlength==0;

2.降序排列后,取第一个(也就是最长的一个进行尝试搜索),如果第一个木棒参与的搜索也失败,就停止。举例子说:比如拿个贪心的sample,比如我拿15凑30,假设不成功,就不必把15替换成11继续搜索。因为如果30是最小长度,则15必须能与其他木棒成功匹配。

3.比如现在我要凑30,我已经有了25,而且我正好找到了5长度的棒子。但是最终失败。至此,这个搜索就可以停止了。因为如果5后面还有比5小的长度,比如1 1 1 1 1,也正好能组成5,但是整数5的灵活性比不上5个1强,整数留到后面给其他棒子匹配也必然失败。(有点贪心的味道)

4.重复的就不用搜索了。

#include "stdio.h"

#include "string.h"

#define MAX 65

 

 

int sticks[MAX] , len , n;

int used[MAX];

 

void sort(int a[] , int begin , int end)

{

    int i , j , tmp ;

 

    for( i = begin+1 ; i <= end ; i++ )

    {

        tmp = a[i];

        for( j = i ; j > begin && a[j-1] < tmp ; j-- )

            a[j] = a[j-1];

        a[j] = tmp;

    }

}

 

int dfs(int i , int l , int t)    // t是棍子长度的总和    l为要拼成时还需要的长度

{

    int j;

 

    if(l == 0)

    {

        t -= len;

 

        if( t == 0)

            return 1;

 

        for( i = 0 ; used[i] ; i++ )  //找到第一个还未使用的棒子

            ;

 

        used[i] = 1;

 

        if(dfs(i+1,len-sticks[i],t))

            return 1;

 

        used[i] = 0;   //如果不适合就将棍子放回去

 

        t += len;  //总长度还是置为原来的总长度

    }

    else

    {

        for( j = i ; j <= n ; j++ )

        {

            if( j > 0 && (sticks[j] == sticks[j-1] && !used[j-1]))

                continue;

 

            if(!used[j]&&l>=sticks[j])

            {

                l -= sticks[j];

 

                used[j] = 1;

 

                if(dfs(j,l,t))

                    return 1;

 

                l += sticks[j];

 

                used[j] = 0;

 

                if(sticks[j]==l)

                    break;

            }

        }

    }

    return 0;

}

 

 

 

 

 

int main()

{

 

    int  i , sum , flag;

 

    while(scanf("%d",&n) && n)

    {

        sum = 0;

 

        flag = 0;

 

        for( i = 0 ; i < n ; i++ )

        {

            scanf("%d",&sticks[i]);

            sum += sticks[i];

            used[i] = 0;

        }

 

        sort(sticks,0,n-1);

 

        for(len = sticks[0]; len <= sum/2; ++len)

        {

            if(sum%len == 0)

            {

                if(dfs(0,len,sum))

                {

                    flag = 1;

                    printf("%d\n",len);

                    break;

                }

            }

        }

        if(!flag)

            printf("%d\n",sum);

    }

 

    return 0;

}

转载于:https://www.cnblogs.com/zuckerTT/archive/2011/09/25/2189859.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值