POJ 1011:木棒

传送门

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

题目大意

已知原来有等长若干木棒,现在给你一堆断了的木棒的长度,问原来的木棒最短是多长

题目类型

DFS + 剪枝 + “贪心优化”

思路

http://blog.csdn.net/lyy289065406/article/details/6647960

三个剪枝

1)设最长的木棒长度max ,木棒长度和sum, 则可能区间为[max, sum/2] 并且 长度能被sum整除

2)一次拼接中,一次循环中,同长度的木棒只检测一次

3)每次拼接的第一个木棒,如果不成功则说明这个木棒一定不能成功。所以break

一个优化

需要逆序搜索。(两个短的比一个长的更有用。)

代码

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
#define N 70

//int visnum;
int mu[N];
bool vis[N];
int n;

int ncount = 0;

bool dfs(int goal,int visnum, int len=0, int s = n-1) {

    ncount++;

    //int succeed = 0;
    if (visnum == n) {
        return true;
    }
    int last = -1;
    for (int i = s; i >= 0; i--) {
        if (vis[i] ||mu[i] == last) continue;
        //if (!vis[i] && mu[i] != last && mu[i] + len <= goal) {
            //last = mu[i];
        vis[i] = true;
        //visnum++;

        if (mu[i] + len < goal) {
            if (dfs(goal,visnum+1, len+mu[i],i)) 
                return true; 
            else last = mu[i];
        } else if (len + mu[i] == goal) {
            if (dfs(goal,visnum+1)) 
                return true; 
            else last = mu[i];
        }

        vis[i] = false;
        //visnum--;

        if (len == 0) break;
        //}
    }
    return false;
}

int main() {
    while (scanf("%d", &n)+1 && n) {
        int i;
        int sum = 0;
        int max = 0;
        for (i = 0; i < n; i++) {
            scanf("%d", &mu[i]);
            sum += mu[i];
            if (mu[i] > max) max = mu[i];
        }
        sort(mu, mu+n);


        //visnum = 0;
        //memset(vis,0,sizeof(vis));
        //printf("454 = %d\n",dfs(454));

        for (i = max; i <= sum/2; i++) {
            if (sum % i == 0) {
                //printf("search %d\n", i);
                //visnum = 0;
                memset(vis, false, sizeof(vis));
                if (dfs(i,0) == 1) break;
                //printf("search end\n");
            }
        }
        //printf("sum = %d\n", sum);
        if (i >= sum/2+1) i = sum;
        printf("%d\n", i);
        //printf("count = %d\n", ncount);
    }
    return 0;
}
View Code

 

posted on 2013-06-24 14:36  ShineCheng  阅读(527)  评论(1编辑  收藏  举报

导航