poj dfs相关之1011 Sticks

来源:互联网 发布:南风知我意2七微 编辑:程序博客网 时间:2024/06/05 07:17

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;                }            }        }    }}
原创粉丝点击