2019牛客多校第六场——D.Move【思维/构造】

链接:https://ac.nowcoder.com/acm/contest/886/D

题目描述

After the struggle of graduating from college, TangTang is about to move from a student apartment to his new home.

TangTang has n items to move, the i-th of which is of volume viv_ivi​. He can pack all these items into at most K boxes of the same volume.
 

TangTang is so clever that he uses the following strategies for packing items:

 

- Each time, he would put items into a box by the next strategy, and then he would try to fill another box.

- For each box, he would put an unpacked item of the largest suitable volume into the box repeatedly until there is no such item that can be fitted in the box.


Now, the question is what is the minimum volume of these boxes required to pack all items.

输入描述:

There are multiple test cases. The first line contains an integer T (1≤T≤201 \leq T \leq 201≤T≤20), indicating the number of test cases. Test cases are given in the following.

For each test case, the first line contains two integers n, K (1≤n,K≤10001 \leq n, K \leq 10001≤n,K≤1000), representing the number of items and the number of boxes respectively.

The second line contains n integers v1v_1v1​, v2v_2v2​, …\ldots…, vnv_nvn​ (1≤v1,v2,…,vn≤10001 \leq v_1, v_2, \ldots, v_n \leq 10001≤v1​,v2​,…,vn​≤1000), where the i-th integer viv_ivi​ represents the volume of the i-th item.

输出描述:

For each test case, output "Case #x: y" in one line (without quotes), where x indicates the case number starting from 1, and y denotes the answer to this test case.

输入

1
5 3
1 2 3 4 5

输出

Case #1: 5

题意:

给你n个物品,k个箱子,每个物品有自己的体积,对于每一个箱子,剩余物品按照从大到小的顺序放入(能放进去就必须要放,放不了就换小的),问能使用至少k个箱子放下所有n个物品的箱子最小容量是多少。

分析:

确定左界(右界可有可无),然后从小到大check当前是否可行,虽然说最坏情况下复杂度说是有1e6*n*n,但是仔细想不会有这种情况,check的次数大约最多只有1000次;

左界是max(sum/k,mx);

 

这玩意儿没有二分性!很气!

原因是:使用较大的箱子装时可能可以装进很多个很大的物品,但剩余的放不进去,于是造成很多的浪费,但如果使用较小的箱子,只能放进去少数几个很大的物品,剩余的空间可以用小物品填充满,浪费更少,所以可能会出现大箱子不行,小箱子反而可以的情况。

39 10

55 63 83 27 16 23 26 26 15 30 56 39 90 53 38 20 100 67 37 43 42 36 18 4 5 56 1 75 71 29 75 18 93 96 5 87 4 38 17

这组数据正解是169,二分的答案可能是171,就是上面说的情况

#include<bits/stdc++.h>
using namespace std;
const int maxn=1010;
int a[maxn],kk[maxn];
int n,k;
bool check(int mid){
    for (int i=1;i<=k;i++) kk[i]=mid;
    for (int i=1;i<=n;i++){
        int f=0;
        for (int j=1;j<=k;j++)
            if (kk[j]>=a[i]){
                kk[j]-=a[i]; f=1; break;
            }          
        if (!f) return false;
    }
    return true;
}
bool cmp(int p,int q){return p>q;}
int main(){
    int t,x,_=0;scanf("%d",&t);
    while (t--){
        scanf("%d%d",&n,&k);
        int sum=0,mx=0;
        for (int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            sum+=a[i]; mx=max(mx,a[i]);
        }
        sort(a+1,a+1+n,cmp);
        int xx;
        if (sum%k==0) xx=sum/k;else xx=sum/k+1;
        xx=max(xx,mx);
        int l=xx,r=sum,mid,ans;
        for (int i=l;i<=r;i++){
            if (check(i)){
                printf("Case #%d: %d\n",++_,i); break;
            }
        }
    }
    return 0;
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值