zoukankan      html  css  js  c++  java
  • B. Box Fitting

    这题的正确性就很神奇 

    给若干个矩形的宽,高都是1,给每层的限定宽度,问最少多少层。

    一般的想法就是每层都尽量填,一直到填不下去为止。

    一种做法是搞一个multiset 然后遍历每个矩形,往最大的那个层丢,不行就开新层

    还有一种做法是,设一层 二分找能丢进去的矩形,直到不能丢进去,然后再设新层,新丢进去,直到搞完。

    还有一种做法是 开log2的桶,每次遍历,反复操作

    void solve(){
        cin>>n>>w;
        multiset<int,greater<int> >s;
        s.insert(w);
        for(int i=1;i<=n;++i){
            cin>>a[i];
        }
        sort(a+1,a+1+n,greater<int>());
        for(int i=1;i<=n;++i){
            int x=*s.begin();
            if(x>=a[i]){
                s.insert(x - a[i]);
                s.erase(s.find(x));
            }
            else{
                s.insert(w-a[i]);
            }
        }
        cout<<s.size()<<"
    ";
    }
    int n,w,cnt[100],x;
    void solve(){
        memset(cnt,0,sizeof(cnt));
        cin>>n>>w;
        for(int i=1;i<=n;++i){
            cin>>x;
            int y=log2(x);
            cnt[y]++;
        }
        int ans=0;
        while(n){//n块 
            ans++;
            x=w;
            for(int i=40;i>=0;--i){
                int now=pow(2,i);
                while(cnt[i]&&x>=now){//当前桶有东西且剩余量够 
                    cnt[i]--;n--;
                    x=x-now;
                }
            }
        }
        cout<<ans<<"
    ";
    }

    关于正确性,确实很神奇

    因为这题都是2的倍数

    所以比如举个例子 8+4+4+2+1>16,那么16一定可以被拆成8+4+4

    也就是说一定可以被拆成前缀

    好,那么假设最优解 为A,我们的贪心解为B

    对每层的块从大到小排序

    如果B的第一块<A的第一块 不可能,因为我们是贪心取的

    如果B的第一块>A的第一块 那么A中再加上后面的几块,

      若加上还小,说明正好多出来几个小块,不能被归并到其他层,贪心解还是正确的

      若加上后大于等于 ,则进行前缀和替换,不影响最优性

    如果B的第一块==A的第一块,好,那么就是最优的

    不是2的倍数不成立

    6 13

    6 6  4 4  3 3

    贪心解中6不能被4 3 替换

  • 相关阅读:
    从零开始学架构(三)UML建模
    【网址收藏】博客园主题美化
    完美解决国内访问GitHub速度太慢的难题
    SpringBoot+slf4j线程池全链路调用日志跟踪 二
    SpringBoot+slf4j实现全链路调用日志跟踪 一
    2021年java最全面试宝典【核心知识整理】
    [中级]系统集成项目管理工程师历年真题及参考答案
    线程池ThreadPoolExecutor最全实战案例
    大厂git分支管理规范:gitflow规范指南
    IdentityServer4
  • 原文地址:https://www.cnblogs.com/PdrEam/p/14716146.html
Copyright © 2011-2022 走看看