zoukankan      html  css  js  c++  java
  • UVA 1149 Bin Packing

    传送门

    A set of n 1-dimensional items have to be packed in identical bins. All bins have exactly the same length l and each item i has length li l. We look for a minimal number of bins q such that

       • each bin contains at most 2 items,

      • each item is packed in one of the q bins,

      • the sum of the lengths of the items packed in a bin does not exceed l.

    You are requested, given the integer values n, l, l1, . . . , ln, to compute the optimal number of bins q.

    Input

    The input begins with a single positive integer on a line by itself indicating the number of the cases following, each of them as described below. This line is followed by a blank line, and there is also a blank line between two consecutive inputs. The first line of the input file contains the number of items n (1 ≤ n ≤ 10^5 ). The second line contains one integer that corresponds to the bin length l ≤ 10000. We then have n lines containing one integer value that represents the length of the items.

    Output

    For each test case, your program has to write the minimal number of bins required to pack all items.

    The outputs of two consecutive cases will be separated by a blank line.

    Note: The sample instance and an optimal solution is shown in the figure below. Items are numbered from 1 to 10 according to the input order.

    Sample Input

    1

    10

    80

    70

    15

    30

    35

    10

    80

    20

    35

    10

    30

    Sample Output

    6

    ------------------------------------------------

    首先注意输出格式,UVA的题常常要求The outputs of two consecutive cases will be separated by a blank line.巨坑。

    Solution:

    Greedy,我的解法是从小到大枚举长度,将每个长度与另一个尽可能大的长度装在一起,若找不到就将这个长度单独装。

    Proof:

    反证法。假设存在一种的方案,其中某个装有两个物品i, j (设length(i)<=length(j))的容器b中的较短的那个物品i不是与能和它装在一起的最长物品k装在一起的,调换kj的位置,得到的是同样优的方案。所以上述贪心策略导致最优方案。

    Implementation:

    实现是用map模拟,太low了。

    #include <bits/stdc++.h>
    using namespace std;
    map<int,int> cnt;
    int main(){
        int T; scanf("%d", &T);
        for(int n, l, cs=0; T--;){
            if(cs++) puts("");
            scanf("%d%d", &n, &l);
            for(int len; n--;) scanf("%d", &len), cnt[len]++;
            int ans=0;
            for(int now; !cnt.empty();){
                now=cnt.begin()->first;
                ans++;
                cnt.begin()->second--;
                if(!cnt.begin()->second){
                    cnt.erase(now);
                }  
                if(cnt.empty()) break;
                auto it=cnt.lower_bound(l-now);
                if(it==cnt.end()) it--;
                for(;;it--){
                    if(it->first<=l-now){
                        it->second--; 
                        if(!it->second){
                            cnt.erase(it->first);
                        }
                        break;
                    }
                    if(it==cnt.begin()) break;
                }
            }
            printf("%d
    ", ans);
        }
    }

    P.S. 我本想用multiset模拟的,但后来发现multiset不支持单个删除相同元素

    multiset<int> s;
    int main(){
        s.insert(10);
        s.insert(10);
        printf("%d
    ", s.size());    //2
        s.erase(10);
        printf("%d
    ", s.size());    //0
    }
  • 相关阅读:
    linux根目录空间不足
    兴趣点 / 关键点( Interest point/Keypoint )
    opencv批量修改图片尺寸
    Excel批量修改文件
    xm数据写入
    opencv矩阵操作
    SVM参数解析
    Mat取行或列
    clone()与image和 cloneTo()
    最大连通域(指针)
  • 原文地址:https://www.cnblogs.com/Patt/p/4842819.html
Copyright © 2011-2022 走看看