HDU - 1455 Sticks(剪枝)

http://acm.hdu.edu.cn/showproblem.php?pid=1455

题意:

给你n个小木棒,问他们能不能拼接成相同的长度,长度最小是多少

思路:

对于n个小木棒,从大到小排序

1.n个小木棒的长度和一定整除与拼接的长度 sum % L == 0

2.拼接的长度大于等于最大长度的小木棒 L >= a[1]

3.对于一个不可行的长度k,那么相同的k不在遍历

比如 5, 4,4,3
DFS先是搜到了(5,4。。。),发现这个方案不成立,那么根据DFS的性质,向前回溯,
搜到了下一个4,那么根据以前的经验,这个4也是不行的」

即对于一个k如果前面有一个未用的k,那么它也是不行的

4.如果一根木棒不能作为长度为L的一根木棒的一部分,那么这个方案L是不可行的,因为每一根小木棒都应该是各自大木棒的一部分,

因为一根大木棒的开始是以降序选择小木棒的,所以一根小木棒开始一根大木棒时,其他的大木棒无法完成,那么把开头的小木棒替换成其他小木棒也无济于事

举例:
left表示这跟木棒还剩多少长度,L是长度为L的方案

10, 9, 2, 4,5 ,sum 为30
从10开始遍历,10可行,9 无法组成10,(即left == L)时,无法成立

9,8,5,4,2,2, sum为30
9无法组成10,(left == L)无法成立

9,8,5,4,1,3, sum为30
9 + 1 == 10,可看成(a[i] == L,仅针对最后一根大木棒的最后一部分)或者(left == L 以a[i] 开头)后续无法组成10,无法成立,

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <math.h>
#include <vector>
#include <set>
#include <map>
#include <string>
#include <string.h>
#include <queue>
#include <stack>
#include <deque>
#include <stdlib.h>
#include <bitset>

using namespace std;

#define ll long long
#define ull unsigned long long
const int INF = 0x3f3f3f3f;
const int maxn = 50 + 5;
const int eps = 1e-8;
const int M = 1e9 + 7;

int pile[maxn];
int a[maxn];
int n;


bool cmp(int a, int b) {
    return a > b;
}

bool vis[maxn];
int L;

bool dfs(int m, int left){
    if(!m && !left)
        return 1;
    if(left == 0)
        left = L;
    for(int i = 1; i <= n; i ++) {
        if(!vis[i] && a[i] <= left) {
            if(i > 1)
                if(!vis[i - 1] && a[i] == a[i - 1]) // 如果以前相同长度的未用,那么这个也不可用
                continue;
        vis[i] = 1;//用了
        if(dfs(m - 1, left - a[i]))//dfs
            return 1;
        else {
            vis[i] = 0;
            if(left == L)//表示以a[i]开始一根木棒,但是它的其他木棒无法完成,那么这个方案无法成立
                return 0;
        }
    }
    }
    return 0;
}

int main(int argc, const char * argv[]) {

    while (scanf("%d", &n) && n) {
        int sum = 0;
        for (int i = 1; i <= n; i ++) {
            scanf("%d", &a[i]);
            pile[a[i]] ++;
            sum += a[i];
        }
        sort(a + 1, a + 1 + n, cmp);
        for (L = a[1]; L <= sum / 2; L ++) {
            if(sum % L) continue;
            memset(vis, 0, sizeof(vis));
            if(dfs(n, L)) {
                printf("%d\n", L);
                break;
            }
        }
        if(L > sum / 2)
            printf("%d\n", sum);
    }


    return 0;
}

猜你喜欢

转载自blog.csdn.net/henu_jizhideqingwa/article/details/81663454