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\n", cas, ans);
    }
    return 0;
}
View Code
posted @ 2019-08-07 11:11  sparkyen  阅读(138)  评论(0编辑  收藏  举报