其他分享
首页 > 其他分享> > dfs之剪枝

dfs之剪枝

作者:互联网

剪枝在dfs的应用——以切木棒问题为例

在dfs中,大致有如下几种剪枝方法:

 

木棒

题目描述:

乔治拿来一组等长的木棒,将它们随机地砍断,使得每一节木棍的长度都不超过 50 个长度单位。
然后他又想把这些木棍恢复到为裁截前的状态,但忘记了初始时有多少木棒以及木棒的初始长度。
请你设计一个程序,帮助乔治计算木棒的可能最小长度。
每一节木棍的长度都用大于零的整数表示。
 
代码如下

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 70;
int n, sum, len;
int w[N], vis[N];


/**
 * now: 当前木棒以拼接的长度
 * u: 搜索到了第几根木棒
 * x: 从第x根木棍开始拼接木棒
 **/
bool dfs(int now, int u, int x) {
    if(u * len == sum) return true;
    if(now == len) return dfs(0, u+1, 0);
    
    // 剪枝2
    for(int i = x; i < n; i++) {
        // 剪枝3
        if(vis[i] || now + w[i] > len) continue;
        
        vis[i] = true;
        if(dfs(now + w[i], u, i + 1)) return true;
        vis[i] = false;
        
        // 剪枝4
        if(now == 0) return false;
        
        // 剪枝5
        if(now + w[i] == len) return false;
        
        // 剪枝6
        int k = i;
        while(w[k] == w[i] && k < n) {
            k++;
        }
        i = k - 1;
    }
    
    return false;
}

int main()
{
    while(cin >> n && n) {
        memset(vis, 0, sizeof vis);
        sum = 0;
        for(int i = 0; i < n; i++) {
            cin >> w[i];
            sum += w[i];
        }
        
        sort(w, w + n);
        reverse(w, w + n);
        
        for(len = 1; ; len ++) {
            // 剪枝1
            if(sum % len == 0 && dfs(0, 0, 0)) {
                cout << len << endl;
                break;
            }
        }
    }
    return 0;
}

 
以下是对代码各处剪枝的说明:

标签:剪枝,木棒,len,int,dfs,木棍,长度
来源: https://blog.csdn.net/PBomb/article/details/114303827