• 2019牛客暑期多校训练营(第六场)D-Move


    >传送门<

    题意:

    你有n件行李,有k个箱子体积相同的箱子,遵循下面的规则将行李放进箱子里面

    每次都取当前最大的可以放进箱子的行李放进箱子,如果该箱子放不进任何行李那么就换一个新的箱子再按照这一条规则进行放行李

    请问箱子最小的体积是多少可以放进所有行李

    思路:

    还是菜鸡的我比赛的时候没有思路,也木有想法,赛后再看题解给出的竟然是暴力枚举!!!

    下面官方题解就分析的挺好的

    • 考虑到答案下界显然为 ceil(sum / k)
    • 上界为 ceil(sum / k) + maxV

    • 假设某个答案 ans 装不下,那么每个箱子的剩余空间都 < maxV
    • 此时 k * (ans - maxV + 1) <= sum
    •  ans <= sum/k + maxV - 1

    • check 一个答案的复杂度为 O(nlogn)
    • 所以我们直接在这个范围内枚举答案,复杂度为 O(maxV * nlogn)

    Code

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 1000 + 7;
    int v[maxn], n, k, used[maxn];
    bool check(int x)
    {
        for(int i = 1; i <= n; i++) used[i] = 0;
        for(int i = 1; i <= k; i++){
            int tmp = 0;
            for(int j = n; j >= 1; j--){
                if(!used[j] && tmp + v[j] <= x){
                    used[j] = 1;
                    tmp += v[j];
                }
            }
        }
        for(int i = 1; i <= n; i++) if(!used[i]) return false;
        return true;
    }
    int main()
    {
        int T;
        scanf("%d", &T);
        for(int cas = 1; cas <= T; cas++){
            scanf("%d%d", &n, &k);
            int sum = 0;
            for(int i = 1; i <= n; i++) scanf("%d", v + i), sum += v[i];
            sort(v + 1, v + n + 1);
            int ans = 1;
            for(int i = sum / k; i <= sum; i++){
                if(check(i)){
                    ans = i;
                    break;
                }
            }
            printf("Case #%d: %d
    ", cas, ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    数学基础详解 1——微积分
    logistic回归梯度上升优化算法
    决策树
    西瓜书学习笔记(1)——模型评估与选择
    关于map与set的一点理解;
    STL中的set容器的一点总结(转)
    HDOJ 题目分类
    Train Problem I(栈)
    猜数字(规律)
    Change the ball(找规律)
  • 原文地址:https://www.cnblogs.com/wizarderror/p/11314127.html
Copyright © 2020-2023  润新知