首页 > 代码库 > POJ 1011 Sticks

POJ 1011 Sticks

http://poj.org/problem?id=1011

 

题意:

给定多根木棒的长度,要求将其重新组合成若干相等长度的木棒,求组合后木棒的最小长度

 

解法:

dfs + 重点剪枝

自己想到的剪枝太弱了 学习整理下看到的剪枝

具体看注释

 

代码:  700K  0MS

#include <iostream>#include <algorithm>#include <cstring>using namespace std;#define _ ios_base::sync_with_stdio(0);cin.tie(0)#define N 64int s[N], sn, l, n, ans;bool flag, vis[N];bool cmp(int a, int b) {    return a > b;}bool dfs(int crtn, int crt, int crtl) {  //在找第几根,当前下标,当前根剩余长度    if (crtn == n) {  //已完成n-1根,必然能完成最后一根        return 1;    }    for (int i = crt; i < sn; ++i) {        if (vis[i] || (i && !vis[i - 1] && s[i] == s[i - 1]) || crtl < s[i]) {  //已选过||已知前一根长度相同的选不上||比剩余长度大            continue;        }        vis[i] = 1;        if (crtl == s[i]) {  //完成当前根            if (dfs(crtn + 1, 0, ans)) {  //从头开始找下一根                return 1;            }            vis[i] = 0;            return 0;  //若找不到下一根,则此测试长度无解        }        else {            if (dfs(crtn, i + 1, crtl - s[i])) {  //接着找当前根                return 1;            }            vis[i] = 0;            if (crtl == ans) {  //从头开始找一根木棍时,若从当前未标记的最长的一根无法找到解,则此测试长度无解                return 0;            }        }    }    return 0;}int main() {    _;    while (cin >> sn && sn) {        int totl = 0;        for (int i = 0; i < sn; ++i) {            cin >> s[i];            totl += s[i];        }        sort(s, s + sn, cmp);  //降序排序        for (ans = s[0]; ans < totl; ++ans) {  //从最长木棍的长度开始增加测试长度            if (totl % ans == 0) {  //测试的长度可整除总长度                memset(vis, 0, sizeof(vis));                n = totl / ans;  //要组的根数                if (dfs(1, 0, ans)) {                    break;  //成功则结束循环                }            }        }        cout << ans << endl;    }    return 0;}

 

POJ 1011 Sticks