zoukankan      html  css  js  c++  java
  • 【bfs】拯救少林神棍(poj1011)

    Description

    乔治拿来一组等长的木棒,将它们随机地砍断,使得每一节木棍的长度都不超过50个长度单位。然后他又想把这些木棍恢复到为裁截前的状态,但忘记了初始时有多少木棒以及木棒的初始长度。请你设计一个程序,帮助乔治计算木棒的可能最小长度。每一节木棍的长度都用大于零的整数表示。

    Input
    输入包含多组数据,每组数据包括两行。第一行是一个不超过64的整数,表示砍断之后共有多少节木棍。第二行是截断以后,所得到的各节木棍的长度。在最后一组数据之后,是一个零。

    Output
    为每组数据,分别输出原始木棒的可能最小长度,每组数据占一行。

    Sample Input
    9
    5 2 1 5 2 1 5 2 1
    4
    1 2 3 4
    0
    Sample Output
    6
    5

    【思路】:bfs,太恶心了~各种优化

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<vector>
    #include<map>
    #include<string>
    #include<cstring>
    using namespace std;
    const int maxn=999999999;
    const int minn=-999999999;
    inline int read() {
        char c = getchar();
        int x = 0, f = 1;
        while(c < '0' || c > '9') {
            if(c == '-') f = -1;
            c = getchar();
        }
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * f;
    }
    int N;
    int L;
    int length[3000];
    int visit[65];
    int i,j,k;
    int my_comp(int x,int y ) {
        return x>y;
    }
    int startNo,lastStickNo=-1;
    int dfs(int R, int M);
    
    int main() {
        while(1) {
            cin >> N;
            if( N == 0 )
                break;
            int he= 0;/*记录总和*/
            memset(length,0,sizeof(length));
            for( int i = 0; i < N; i ++ ) {
                int n;
                cin >> length[i];
                he+= length[i];
            }
            sort(length,length+N,
                 my_comp);
            for( L = length[0]; L <= he/ 2; L ++ ) {
                if( he% L)
                    continue;
                memset( visit, 0,sizeof(visit));
                if( dfs( N,L)) {
                    cout << L << endl;
                    break;
                }
            }
            if( L > he/ 2 )
                cout << he<< endl;
        }
        return 0;
    }
    int dfs( int R, int M) { /*m表示当前正在拼接的木棍和我们枚举的长度L的差距*/
        if( R == 0 && M == 0 )
            return true;
        if( M==0 ) // 一根刚刚拼完的时候换新的一根
            M=L;
        int start= 0;
        int startNo = 0;
        if( M != L ) //剪枝:不选第一个
            startNo = lastStickNo + 1;
        for( int i =  startNo; i < N; i ++) {
            if( !visit[i] && length[i] <= M) {
                if( i > 0 ) {
                    if( visit[i-1] == 0 && length[i] == length[i-1])
                        continue; // 剪枝 如果某次拼接选择长度为S 的木棒,导致最失败,则在 同一位置尝试下一根木棒时,要跳过所有长度为S 的木棒
                }
                visit[i] = 1;
                lastStickNo = i;
                if ( dfs( R - 1, M - length[i]))
                    return true;
                else
                    /*回溯*/
                    visit[i] = 0;
                if( M == L)//剪枝
                    return 0;
            }
        }
        return false;
    }
  • 相关阅读:
    7.29随堂笔记
    LeetCode77. 组合
    347. 前 K 个高频元素
    LeetCode239. 滑动窗口最大值
    C++_数字字符串互相转换
    LeetCode150. 逆波兰表达式求值
    LeetCode1047. 删除字符串中的所有相邻重复项
    LeetCode20. 有效的括号
    Leetcode225. 用队列实现栈 && LeetCode232. 用栈实现队列
    leetCode5663. 找出第 K 大的异或坐标值
  • 原文地址:https://www.cnblogs.com/pyyyyyy/p/10736561.html
Copyright © 2011-2022 走看看