zoukankan      html  css  js  c++  java
  • 牛客多校第六场 D move 枚举/机智题

    题意:

    有个家伙装东西,他的策略是贪心,每次装进去这个盒子能装下的最大的东西,直到把这个盒子装满,再去装下一个盒子。

    给出盒子的数量k和一些东西的重量,问你最小需要多大的盒子才能以这种贪心策略装下。

    题解:

    如果某个解可行,比它大的值未必可行,比如有15个物品,5个39,5个60,5个100,5个盒子,那么盒子大小199可以,200不行,201也不行。所以不能二分。

    首先,显然答案下界为ceil(sum/k)。

    设最大的物品重量为maxv,假如某个ans装不下,那么在此ans下,装下除maxv外所有物品后,所有箱子的剩余空间都小于maxv

    因此,ans*k<sum-maxv+k*maxv

    只需在[ceil(sum/k),ceil(sum/k+(k-1)*maxv)]区间内枚举即可。

    判断一个ans的可行性复杂度是nlogn

    #include<bits/stdc++.h>
    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    #define MAXN 1005
    #define mem(a,b) memset(a,b,sizeof a)
    #define rep(i,n,m) for(int i=n;i<=m;++i)
    const int MOD = 9973;
    inline int read()
    {
        int x = 0, f = 1;
        char c = getchar();
        while (c<'0' || c>'9')
        {
            if (c == '-') f = -1;
            c = getchar();
        }
        while (c >= '0' && c <= '9')
        {
            x = x * 10 + c - '0';
            c = getchar();
        }
        return x * f;
    }
    int v[MAXN], n, k, num[MAXN], vis[MAXN],num1[MAXN];
    bool check(int vlo)
    {
        int nu = k;
        mem(vis, 0);
        //是否可以装完所有物品,贪心的装,尽量装大的,然后再补漏
        int left = n;
        //rep(i, 1, 1000) num1[i] = num[i];
        int maxx = n,no=1;
        while (nu)
        {
            int sp = vlo;
            for (int i = maxx; i > 0; --i)
            {
                if (sp < v[no]) break;
                if (sp >= v[i] && !vis[i])
                {
                    sp -= v[i]; vis[i] = 1; left--;
                    if (!sp) break;
                }
            }
            while (vis[maxx]) maxx--;
            while (vis[no]) no++;
            nu--;
        }
        if (!left) return 1;
        return 0;
    }
    int main()
    {
        int T = read();
        for(int tt=1;tt<=T;++tt)
        {
            int sum = 0;
            n = read(), k = read();
            mem(num, 0);
            mem(num1, 0);
            rep(i, 1, n) v[i] = read(), sum += v[i];
            sort(v + 1, v + 1 + n);
            int bi = sum / k;
            if (sum % k) bi++;
            int beg = max(v[n], bi);
            int ans=beg;
            for (int i = beg; i <= 1000000; ++i)
            {
                if (check(i)) {
                    ans = i; break;
                }
            }
            printf("Case #%d: %d
    ", tt,ans);
        }
    }
  • 相关阅读:
    发现勤洗手可以有效提高机械键盘的手感
    linux过滤文本中含有关键字的行
    Shell中$0、$1、$2含义
    流计算
    Java 版本tensorflow模型推理实现(基于bert命名实体、基于transform文本分类)
    bert文本分类模型保存为savedmodel方式
    修正数据到json格式
    实际应用中的词向量维度使用注意
    找出一组数据中重复数据
    快速进行词向量训练和读取
  • 原文地址:https://www.cnblogs.com/isakovsky/p/11296773.html
Copyright © 2011-2022 走看看