• zzuli 1432(二进制特点)


    1432: 背包again

    Time Limit: 1 Sec  Memory Limit: 128 MB
    Submit: 222  Solved: 65

    SubmitStatusWeb Board

    Description

    Gy最近学习了01背包问题,无聊的他又想到了一个新的问题,给定n个物品的价值,和01背包一样,每个物品只能选1次或0次,求最小不能被得到的价值。

    Input

    第一行一个正整数T(T <= 100),表示有T组数据。

    每组数据输入格式如下:

    第一行为一个正整数N(N<=100),表示物品个数。

    第二行N个正整数,表示每个物品的价值vi(1<=vi<=1000000)

    Output

    共输出T行,即每组数据相应答案。

    Sample Input

    2 3 2 4 8 4 1 2 4 8

    Sample Output

    1 16

    可恶的数学题!

    二进制表示,例:1=2^0,2=2^1,4=2^2,8=2^3

    又二进制的1111=2^3+2^2+2^1+2^0=15;

    不难看出,1111(即15以内所有的数)均可以用:2^0,2^1,2^2,2^3的二进制表示出来(1101,1001,1000,0101…………),那一位是1就加上这位代表的值(2^x)

    所以证明了结论的正确性!

    不难发现,类似于背包的二进制分解,1,2,4,8。......2^n,

    对于这类连续的二的次方数,只要是下一个次方数以内的数,均可以用这几个书中的某几个表示出来;

    例如    1,2,4,8  则16(不包含16) 以内的数均可以用这几个数表示;

    所以打表出这些数,然后与比对,注意坑:要将数据先sort完之后再比对!!!!坑死我了

    最后在筛查一下,对于大于maxn的数不必再考虑,找到小于maxn的数后,就让其加上这个值,因为maxn以内的值均可以表示了,

    如果再出现一个小于maxn的数a,则maxn+a以内的数也就都可以表示了。

    如果a大于maxn的话最小能表示的也是maxn+1还是没maxn小,所以不必考虑。

    #include<bits/stdc++.h>
    using namespace std;
    int p[105]={1};
    int main()
    {
    int t,i,j,n,k,a[105];
    for(i=1;i<=27;++i) p[i]=p[i-1]*2;


    cin>>t;
    while(t--){int maxn=1;
    cin>>n;
    for(i=1;i<=n;++i) cin>>a[i];
    sort(a+1,a+n+1);
    for(i=1,j=0;i<=n;++i) if(a[i]==p[j]) {maxn=p[j+1];a[i]=0;++j;}

    for(i=1;i<=n;++i){
    if(a[i]&&a[i]<maxn) maxn+=a[i];
    }
    cout<<maxn<<endl;
    }
    return 0;
    }

  • 相关阅读:
    HDU1712:ACboy needs your help(分组背包模板)
    HDU1203:I NEED A OFFER!(01背包)
    HDU1171:Big Event in HDU
    POJ1014:Dividing(多重背包)
    HDU2191-悼念512汶川大地震遇难同胞——珍惜现在,感恩生活(多重背包入门)
    hdu2159FATE(二维背包)
    POJ1201 Intervals
    C++之运算符重载
    C++之强制类型转换
    MFC WinInetHttp抓取网页代码内容
  • 原文地址:https://www.cnblogs.com/zzqc/p/6650766.html
Copyright © 2020-2023  润新知