• A1103 Integer Factorization (30 分)


    这道题我是根据晴神 DFS() 这一节给出的两个例子归纳的模板 AC 的,但实际上剪枝还不够完美 :-(

    先说晴神 DFS 小节第一个例子

    有 n 件物品,每件物品的重量为 w[i],价值为 c[i]。现在需要选出若干件物品放入一个容量为 V 的背包中,使得在选入背包的物品重量和不超过容量 V 的前提下,让背包中物品的价值之和最大,求最大价值。(1≤n≤20)

    晴神给出的代码如下:

    void DFS(int index, int sumW, int sumC) {
        //死胡同
        if (index == n) {
            return;//已经完成对 n 件物品的选择
        }
    
        //岔道口
        DFS(index + 1, sumW, sumC);//不选第 index 件物品
        if (sumW + w[index] <= V) {//只有加入第 index 件物品后未超过容量 V,才能继续
            if (sumC + c[index] > ans) {
                ans = sumC + c[index];//更新最大价值 maxValue
            }
            DFS(index + 1, sumW + w[index], sumC + c[index]);//选第 index 件物品
        }
    }

    根据这个算法我粗略地模拟了一下程序执行过程:

    发现 DFS() 特点就是 1) 遍历所有子序列;2) 每个子序列都遍历到底,然后稍微总结了一下模板

    /* 模板大概如下 */
    void DFS(当前元素, 其他条件的数据..) {
        //死胡同
        if (当前为第 n 个元素)    return;
    
        //岔道口
        DFS(不选当前元素);
        if (剪枝条件)    DFS(选当前元素);
    }

    本来想尝试用这个模板做一下晴神 DFS 小节第二个例子,但是这个例子有点不同,先看例子:

    给定 N 个整数(可能有负数),从中选择 K 个数,使得这 K 个数之和恰好等于一个给定的整数 X;如果有多种方案,选择它们中元素平方和最大的一个。数据保证这样的方案唯一。例如,从 4 个整数 {2, 3, 3, 4} 中选择 2 个数,使它们的和为 6,显然有两种方案 {2, 4} 和 {3, 3},其中平方和最大的方案为 {2, 4}。

    同样晴神给出了代码:

    void DFS(int index, int nowK, int sum, int sumSqu) {
        if (nowK == k && sum == x) {//找到 k 个数的和为 X
            if (sumSqu > maxSumSqu) {//如果比当前找到的更优
                maxSumSqu = sumSqu;//更新最大平方和
                ans = temp;//更新最优方案
            }
            return;
        }
        //已经处理完 n 个数,或者超过 k 个数,或者和超过 x,返回
        if (index == n || nowK > k || sum > x)    return;
    
        //选 index 号数
        temp.push_back(A[index]);
        DFS(index + 1, nowK + 1, sum + A[index], sumSqu + A[index] * A[index]);
        temp.pop_back();
        //不选 index 号数
        DFS(index + 1, nowK, sum, sumSqu);
    }

    同样我也粗略模拟了一下

    相比上一个例子,这个例子就多了个 "结果不唯一",这需要记录每次满足条件的结果。晴神这边处理方法是多增加了一个逻辑块,让符合条件的所有结果都进来,然后在这里根据不唯一的条件再筛选一次。至于如何保存之前尝试的选择,晴神就是在 "选这个元素" 的前面和后面加一个  .push_back() 和  .pop_back() ,然后在这个筛选不唯一结果的逻辑块中更新这些尝试

    /* 然后我改了一下模板 */
    void DFS(当前元素, 其他条件..) {
        if (满足条件) {
            if (不唯一条件)    {...}
            return;
        }
        if (死胡同)    return;
    
        //岔道口
        DFS(不选当前元素);
        if (剪枝条件)    DFS(选当前元素);
    }

    最后我用这个模板试了一下 A1103,思路如下:

    /* 思路 */
    
    题目要求:
    1、找 K 个数
    2、这 K 个数的 P 方和等于 N
    3、不唯一时找因子和最大的
    
    模板中需要填充的地方:
    1、形参中的 "其他条件" 就是题目的要求:
        K 个数:                 可以用 sumNum 记录选了几个数
        这 K 个数的 P 方和等于 N:可以用 sumPower 记录已选数的 P 方和
        不唯一时找因子和最大的:   可以用 sumFactor 记录已选数和
    2、判断 1"满足条件" 是指:
        (选了 K 个数) && (这 K 个数的 P 方和等于 N)
    3、判断 1 里面的判断条件 "不唯一条件" 是指:
        因子和最大
    4"死胡同" 是指:
        (选完了所有元素) || (超过了 K 个数) || (K 个数的 P 方和大于 N)

    最后确实能 AC,但我尝试了跑数据范围内最大的  400 399 2 非常非常非常非常久,我又试了试柳婼大神的代码

     

    :-( 

    优化留着以后再看了,继续撸下一节 XD

    点击获取完整代码

  • 相关阅读:
    BZOJ1057:[ZJOI2007]棋盘制作——题解
    洛谷4147:玉蟾宫——题解
    洛谷1578:[WC2002]奶牛浴场——题解
    BZOJ1926:[SDOI2010]粟粟的书架——题解
    BZOJ3123:[SDOI2013]森林——题解
    BZOJ1834:[ZJOI2010]网络扩容——题解
    BZOJ2668:[CQOI2012]交换棋子——题解
    BZOJ1070:[SCOI2007]修车——题解
    BZOJ1877:[SDOI2009]晨跑——题解
    在阿里,我们如何管理测试环境
  • 原文地址:https://www.cnblogs.com/bEngi1/p/14404158.html
Copyright © 2020-2023  润新知