• P2392 kkksc03考前临时抱佛脚题解


    题目传送门

    1、深度优先搜索

    #include <bits/stdc++.h>
    
    using namespace std;
    const int INF = 0x3f3f3f3f;
    int res;            //每一科目试题时间总和
    int s[20 + 10];     //科目数量
    int a[60 + 10];     //每一道题目需要的时间
    
    int n;              //当前科目的试题数量
    int m;              //当前科目完成试题的最短时间
    
    /**
     * 功能:本科目的试题,dfs跑所有情况。
     * @param ans   当前选择路线上的时间长度值
     * @param step  正在处理第几个试题
     * @param cnt   当前科目一共多少个试题
     */
    void dfs(int step, int ans) {
        //step从站在1位置开始,向下一个位置进行眺望,如果已经站在n的位置上了,就表示该进行总结了~
        if (step == n + 1) {
            //如果ans代表前一半的话,那么res-ans就代表另一半,这两半谁大就是这组方案的解
            m = min(m, max(ans, res - ans));//找出方案的最小值
            return;
        }
        //不要下一道题
        dfs(step + 1, ans);
        //要上下一道题
        dfs(step + 1, ans + a[step + 1]);
    }
    
    int main() {
        //读入四科的题目数量
        for (int i = 1; i <= 4; i++) cin >> s[i];
        int sum = 0;
    
        //遍历每一科,进行试题处理
        for (int i = 1; i <= 4; i++) {
            //本科目的所有试题总时长
            res = 0;
            //初始化数组
            memset(a, 0, sizeof a);
            //读入试题需要的时间
            for (int j = 1; j <= s[i]; j++) {
                cin >> a[j];
                res += a[j];//计算总的时长
            }
            //当前科目的试题数量
            n = s[i];
            //逐科目开始找出最短的复习时间
            m = INF;//预求最小,先设最大
            //暴搜
            dfs(1, 0);
            //暴搜的结果在m里,把m加到总和中
            sum += m;
        }
        //输出总和
        cout << sum << endl;
        return 0;
    }
    
    

    2、01背包

    #include <bits/stdc++.h>
    
    using namespace std;
    int s1, s2, s3, s4; //4科的题目数量
    
    //20是每个科目的题目数量上限
    //60是每道题消耗的最长时间上限
    //题目数据上限为20*60,这里设置为1210,保证不会越界
    const int N = 610; //背包的最大容量是 20*60,我们设置1200就可以,但实际上我们只需要一半的容量,就是610就行了。
    int w[N], v[N], f[N];
    
    int bag(int n) {
        int sum = 0; //当前科目中所有习题的时长总和
        memset(f, 0, sizeof(f));
    
        for (int i = 1; i <= n; i++) {
            cin >> w[i];
            v[i] = w[i]; //此题中的价值v和重量w是同一个概念,背包上限的是总时间的一半,放入一个习题,就占用了v[i]的时间,产生了v[i]的价值
            sum += w[i]; //总时长
        }
        //总时长的一半,就是尽量想办法装满一半的容量
        int m = sum / 2;
    
        //01背包模板
        for (int i = 1; i <= n; i++)
            for (int j = m; j >= w[i]; j--) // sum/2就是背包的上限,因为一半尽量装满,则不是这半最佳就是另一半最佳。
                f[j] = max(f[j], f[j - w[i]] + v[i]);
    
        //两半取最大的一半就是本科目的时长
        return max(f[m], sum - f[m]);
    }
    
    int main() {
        //需要考4科
        cin >> s1 >> s2 >> s3 >> s4;
        int ans = bag(s1) + bag(s2) + bag(s3) + bag(s4); //一科一科的整,四个背包最优解的总和
        cout << ans << endl;
        return 0;
    }
    
  • 相关阅读:
    0309. Best Time to Buy and Sell Stock with Cooldown (M)
    0621. Task Scheduler (M)
    0106. Construct Binary Tree from Inorder and Postorder Traversal (M)
    0258. Add Digits (E)
    0154. Find Minimum in Rotated Sorted Array II (H)
    0797. All Paths From Source to Target (M)
    0260. Single Number III (M)
    0072. Edit Distance (H)
    0103. Binary Tree Zigzag Level Order Traversal (M)
    0312. Burst Balloons (H)
  • 原文地址:https://www.cnblogs.com/littlehb/p/15062072.html
Copyright © 2020-2023  润新知