poj-1011-Sticks-(dfs+剪枝)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_33096883/article/details/77533152

题目地址

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

题目大意

给出n个小木棒,组合成若干长度最短棍子

解题思路

  • 首先将木棒从大到小排序
  • dfs(k, l), k是还剩多少木棒没用,l是当前没组装成功的棍子还需多长木棒
  • 剪枝
    • 选取能被木棒总长度能整除的棍子长度
    • 如果当前选取木棒的长度比所需的长度大,剪枝
    • 如果剩余的木棒总长度还没所需的长度大,剪枝
    • dfs每一次开始选取木棒,要从上一次选取的后面开始
    • 对于相等的木棒,如果一次不成功,就无需再次尝试

Code

#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <queue>
#include <map>
#include <vector>
#include <math.h>
#include <algorithm>
#define INF 0x3fffffff
#define N 80

using namespace std;
typedef long long LL;


int n;
int g_min;

int a[N];
int v[N];
int L;
int last;
// k is the num of remain sticks
// l is cur need length
bool dfs(int k, int l) {
    if (k == 0 && l == 0) {
        return true;
    }
    if (k == 0 && l != 0) {
        return false;
    }

    if (l == 0) {
        l = L;
    }

    // cut
    int st = 0;
    if (l != L) {
        // last : pre used pos
        st = last + 1;
    }

    for (int i = st; i < n; i++) {
        if (v[i]) continue;
        if (a[i] > l) continue;
        // same length
        if (i > 0 && v[i-1] == 0 && a[i] == a[i-1]) continue;
        // the all remain is not enough
        int sum = 0;
        for (int j = i; j < n; j++) {
            sum += a[j];
        }
        if (sum < l) {
            return false;
        }
        // dfs
        v[i] = 1;
        last = i;
        if (dfs(k-1, l-a[i])) {
            return true;
        } else {
            v[i] = 0;
            // the first staick
            // suggest that the len is not good
            if (l == L) {
                return false;
            }
        }
    }
    return false;
}

int main() {

#ifndef ONLINE_JUDGE
    freopen("in", "r", stdin);
#else
    //
#endif

    while (cin >> n) {
        if (n == 0) break;
        int sum = 0;
        for (int i = 0; i < n; i++) {
            scanf("%d", &a[i]);
            sum +=  a[i];
        }
        // large is first
        sort(a, a+n, greater<int>());
        for (L = a[0]; L <= sum/2; L++) {
            if ((sum % L) != 0) continue;
            memset(v, 0, sizeof(v));
            if (dfs(n, L)) {
                printf("%d\n", L);
                break;
            }
        }
        if (L > sum/2) {
            printf("%d\n", sum);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_33096883/article/details/77533152