• 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
    ",dfs(454));
    
            for (i = max; i <= sum/2; i++) {
                if (sum % i == 0) {
                    //printf("search %d
    ", i);
                    //visnum = 0;
                    memset(vis, false, sizeof(vis));
                    if (dfs(i,0) == 1) break;
                    //printf("search end
    ");
                }
            }
            //printf("sum = %d
    ", sum);
            if (i >= sum/2+1) i = sum;
            printf("%d
    ", i);
            //printf("count = %d
    ", ncount);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    学习进度条
    学期总结
    实验四主存空间的分配和回收
    学术诚信与职业道德
    《构建之法》第8,9,10章 读后感
    实验三 进程调度模拟程序
    团队项目:学习四则运算,团队准备 3.0
    团队项目:学习四则运算,团队准备 2.0
    "数学口袋精灵"bug(团队)
    实验二作业调度模拟程序
  • 原文地址:https://www.cnblogs.com/shinecheng/p/3152394.html
Copyright © 2020-2023  润新知