poj dfs相关之1011 Sticks

poj dfs相关之1011 Sticks

这道题是比较经典的回溯题,而且剪枝很重要,不然会超时:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 70;
int n, ans, len,num;
int stick[maxn];
bool mark[maxn];
bool cmp(int i, int j)
{
    return i > j;
}
bool dfs(int sum, int dep, int i)
{

    if (dep == num - 1)//剪枝1:与dep==num等价,剩下的构成最后一个小棒
    {
        ans = 1;
        return true;
    }
    if (ans)
        return true;
    int t, tmp;
    for (t = i; t < n; t++)
    {
        if (mark[t] == 1)
            continue;
        mark[t] = 1;
        if (sum + stick[t] < len)
        {
            if (dfs(sum + stick[t], dep, i + 1))
                return true;
        }
        else if (sum + stick[t] == len)
        {
            if (dfs(0, dep + 1, 0))
                return true;
        }

        mark[t] = 0;
        if (sum == 0)//剪枝2:如果第一个小棒就找不到组合的话(此时所有递归都退出到这儿,和为0),则break。这里如果不剪枝的话一定会超时
            break;
        while (stick[t] == stick[t + 1] && t < n)t++;//剪枝3,stick[t]不行的话,与他相同的也不行(前提是降序排列)
    }
    return false;

}
int main()
{
    freopen("1.txt", "r", stdin);
    int i, j, k, sum;
    while (scanf("%d", &n) != EOF&&n != 0)
    {
        k = 0;
        sum = 0;
        for (i = 0; i < n; i++)
        {
            scanf("%d", &stick[i]);
            k = max(k, stick[i]);
            sum += stick[i];
        }
        sort(stick, stick + n, cmp);
        for (len = k; len <= sum; len++)//剪枝4:循环从K开始
        {
            if (sum%len == 0)
            {
                memset(mark, 0, sizeof(mark));
                ans = 0;
                num = sum / len;
                dfs(0, 0, 0);
                if (ans)
                {
                    printf("%d\n", len);
                    break;
                }
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值