zoukankan      html  css  js  c++  java
  • Knapsack Packing(思维+multiset)

    题意:

       给定一个集合A,包含2^N个数,问是否存在N个数可以组合成A。

    思路:

      假设存在N个数可以组合成A。取出A中最大的两个数Firs,Second;x=First-Second,x一定位N个数中的一个数;集合A中的元素按照是否包含x可以划分为A+(包含x),A-(不包含x);且A+的大小=A-的大小=2^(N-1);

      A-可以看作是剩下的N-1个元素组合而成的集合,将A-迭代A(A=A-),继续执行上述操作,集合的大小不断变为原来的1/2,直至最终只剩下一个元素0;

      

      {

      如何不重不漏的求得所有不包含x的元素,即如何求得A-?

      首先将A中的所有元素单调不减的顺序排列,然后从小到大处理。

      序列S:不包含x的元素所形成的序列。初始为空。

      A中的第一个元素为0,将0加入S。

      假设序列S已有:a1,a2……ak,且a1+x,a2+x,……ak+x都已经从A中删除,则aK+1一定不包含x。

      证明:假设ak+1包含x

        1、若ak+1-x小于等于ak,则ai+x(1<=i<=k)未删除,与已知矛盾。

        2、若ak+1-x大于ak,则ak+1不是大于ak的第一个元素,与假设矛盾。

      固假设错误,所以ak+1不包含x。

      将ak+1加入序列S,并将aK+1+x从A中删除。重复执行加入删除的步骤,直至A为空,此时S即为A-。

      }

      以上为必要条件,即若存在N个元素可以组合成A,则以上条件满足。

      若A可以重复的用A-迭代,直至最后只剩下一个0,那么也存在N个元素可以组合成A。

    /*
    来自题解
    给你n件物品和他们的重量和所有组合,求是否存在这n件物品的重量,满足这些组合
    */
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <cctype>
    #include <iostream>
    #include <algorithm>
    #include <map>
    #include <set>
    #include <vector>
    #include <string>
    #include <stack>
    #include <queue>
    
    typedef long long LL;
    using namespace std;
    
    int n, ans[25];
    
    multiset<int> s;
    
    int main()
    {
        //freopen("in.txt", "r", stdin);
        //freopen("out.txt", "w", stdout);
    
        scanf("%d", &n);
        for (int i = 0, x; i < (1 << n); i++) scanf("%d", &x), s.insert(x);
        int cnt = 0;
        for (int i = 1; i <= n; i++){
            if(s.size() < 2) break;
            cnt++;
            int x = *prev(s.end()) - *prev(prev(s.end()));
            ans[i] = x;
            for (auto it = s.begin(); it != s.end(); it++){
                int y = *it;
                auto p = s.upper_bound(x + y);
                p = prev(p);
                if(p == s.end() || p == it || *p != x + y){
                    printf("impossible
    ");
                    return 0;
                }
                s.erase(p);
            }
        }
        if(s.size() != 1 || *s.begin() != 0 || cnt < n) printf("impossible
    ");
        else for (int i = 1; i <= n; i++) printf("%d
    ", ans[i]);
    
        return 0;
    }
    /**/

     

  • 相关阅读:
    华硕ASUS A3V 拆解图 http://m.linktone.com/report/pdjj/14001781862.shtml
    华硕A3V 迅驰 配置详情
    Dvbbs 更换论坛置顶图片
    Flash 图片轮换效果
    动网官方最新dvbbs7.1sp1商业版下载,附存储过程解密代码!
    在VC中为应用程序添加图形超链接功能
    VC常见数据类型转换详解
    查询Access逻辑字段遇到的问题 武胜
    几个不错的开源的.net界面控件 转自http://zchuang2004.spaces.live.com/blog/cns!8C4AEEE059DED8B1!157.entry 武胜
    C#正则表达式整理备忘 转载(http://www.cnblogs.com/KissKnife/archive/2008/03/23/1118423.html) 武胜
  • 原文地址:https://www.cnblogs.com/dialectics/p/12523385.html
Copyright © 2011-2022 走看看