• D


    D - 小木棒

    Time Limit: 1000/1000MS (C++/Others) Memory Limit: 65536/65536KB (C++/Others)

    Problem Description

    George有一些长度相等的木棒,他随意的将这些木棒切成长度最多是50的小木棒。麻烦来了,他现在想将这些杂乱的小木棒恢复到原来的木棒,但是他忘记了原来到木棒的数量和长度。请你帮助他设计一个程序计算出原来木棒可能的最小长度,所有小木棒的长度均表示为大于0的整数。

    Input

    每组输入数据包括两行。第一行是George切后小木棒的个数,最多有64根小木棒;第二行是这些小木棒的长度,这些长度表示为空格分开的整数。输入样例以整数0表示结束。

    Output

    输出一行,即为原始木棒可能的最小长度。

    Sample Input

    9
    5 2 1 5 2 1 5 2 1
    4
    1 2 3 4
    0

    Sample Output

    6
    5




    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    int a[105], n, now;
    bool vis[105];
    
    bool dfs(int len, int cnt, int p){ //当前需要的木棍长度,当前已拼接的木棍个数,当前拼接的下标
    
        if(cnt == n) return true;      //已经拼成了n个木棍,可行
        if(len == 0) {                 //当前需要的木棍长度为0
            len = now;                 //把len置为当前检测长度 now
            p = n;                     //把搜索下标置为最大
        }
    
        int lst = 0;
        for(int i=p-1; i>=0; i--){     //剪枝:再同一根木棍的拼凑中,不用反复搜索较大木棍,[0, p]
            if(!vis[i] && a[i] <= len && a[i] != lst){ //剪枝:如果和上一个不可行长度相等,则跳过
                vis[i] = true;         // 取当前木棍 再搜索
                if(dfs(len - a[i], cnt + 1, i)) // 可行 return true
                    return true;
                vis[i] = false;       // 不可行,则需要回退状态,不选当前木棍
                lst = a[i];           // 记录上一个不可行的木棍,和这个相等的都不用判
                if(len == now) return false; // 剪枝: 如果有任何一个不能构成len长度,则return false
            }
        }
        return false;
    }
    
    int main(){
        int maxx, sum, ans; // 分别记录最长的木棍,总长度,答案
        while(~scanf("%d", &n) && n){
            sum = 0;
            for(int i=0; i<n; i++) {
                scanf("%d", &a[i]);
                sum += a[i];
            }
            sort(a, a+n);  //sort 默认升序排序
            maxx = a[n-1]; //取最大的元素
            ans = sum;     //ans初始化为sum,如果[maxx, sum/2]范围内都找不到解,一定是全部合成一根
    
            for(int i=maxx; i<=sum/2; i++){ //剪枝:如果[maxx, sum/2]范围内都找不到解,答案是sum
                if(sum%i == 0) {   //剪枝:当i是sum的因子,才有可能是原木棍长度
                    memset(vis, 0, sizeof vis); //每次搜索前,把所有木棍置为未选择状态
                    now = i;                    //当前搜索的目标长度是i
    
                    if(dfs(i, 0, n)) {
                        ans = i;                //剪枝:找到的第一组可行解直接跳出
                        break;
                    }
                }
            }
            printf("%d
    ", ans);
        }
        return 0;
    }
  • 相关阅读:
    数组集合之间的转换
    eclipse 大小写转换
    Linux下查看文件内容的命令
    linux常用命令:创建文件和文件夹
    Error Downloading Packages: yum更新出现错误
    XShell上传文件到Linux服务器上
    linux最常用的20个命令
    Sonar理论篇
    如何查看DLL文件的函数列表
    C++在C的基础上的扩充
  • 原文地址:https://www.cnblogs.com/yangf428/p/10180793.html
Copyright © 2020-2023  润新知