zoukankan      html  css  js  c++  java
  • a.Baby Coins

    a: Baby Coins

    Time Limit: 1 Sec  Memory Limit: 128 MB

    Description

    Baby 今天清点自己的百宝箱啦,箱子里有 n 种硬币,硬币的面值分别是:val[1],val[2],...,val[n],每种面值的硬币都恰好有 2 个。Baby 实在闲的太无聊了,他想从他所拥有的硬币中选出若干个,使得面值之和为 k。那么他的目标能否实现呢 ~

    Input


    每一组数据第一行都包含两个数字 n(n≤18),k(1≤k≤1e9)。n 代表箱子中所包含的硬币种数,k 代表 Baby 需要组成的金钱数额。接下来的一行代表 val[1],val[2],......,val[n]。(1≤val[i]≤ 1e7)

    Output

    如果Baby能组成金钱数额k,请输出Yes,否则输出No。

    Sample Input

    2
    2 10
    3 4
    3 9
    1 2 10
    

    Sample Output

    Case 1: Yes
    Case 2: No
    

    折半枚举,先假设每种硬币只能选一次,枚举出所有可能性的和存到一个数组里(O(n*2^n)),然后把数组排序二分查找,比如一种可能性是a[i],那我们只要看k-a[i]是不是也在这个数组里就行了。

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 #define rd(a) scanf("%d",&a)
     5 #define rep(i,a,b) for(int i=(a);i<=(b);i++) 
     6 int v[25],a[300000];
     7 int main(){
     8     int T;
     9     rd(T);
    10     rep(tt,1,T){
    11         int n,k;
    12         rd(n);rd(k);
    13         for(int i=0;i<n;i++)rd(v[i]);
    14         int cnt=0;
    15         bool flag=0;
    16         for(int i=0;i<(1<<n);i++){//枚举所有可能性
    17             int tot=0;
    18             for(int j=0;j<n;j++){
    19                 if(i&(1<<j))tot+=v[j];
    20             }
    21             if(tot==k)flag=1;
    22             if(tot<k)a[cnt++]=tot;
    23         }
    24         sort(a,a+cnt);
    25         for(int i=0;i<cnt;i++)
    26             if(binary_search(a,a+cnt,k-a[i]))flag=1;
    27         printf("Case %d: %s
    ",tt,flag?"Yes":"No");
    28     }
    29 }
    View Code
    
    
    
     经过大佬指点之后发现还可以换一种思路枚举,这里我们把硬币平均分成前后两组,每一组分别枚举取0,1,2枚硬币的状态(O(n*3^(n/2))),然后在前后两组用二分找是否有和为k的就行了。

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 #define rd(a) scanf("%d",&a)
     5 #define rep(i,a,b) for(int i=(a);i<=(b);i++) 
     6 int v[25],a[20000],b[20000],sum,pow3[20]={1};
     7 bool judge(int n,int k){
     8     if(sum<k)return 0;
     9     int cnta=0,cntb=0;
    10     for(int i=0;i<pow3[n/2];i++){
    11         int tot=0,t=i;
    12         for(int j=n/2-1;j>=0;j--){
    13             while(t>=pow3[j])
    14                 tot+=v[j],t-=pow3[j];
    15         }
    16         if(tot==k)return 1;
    17         if(tot<k)a[cnta++]=tot;
    18     }
    19     for(int i=0;i<pow3[n-n/2];i++){
    20         int tot=0,t=i;
    21         for(int j=n-1;j>=n/2;j--){
    22             while(t>=pow3[j-n/2])
    23                 tot+=v[j],t-=pow3[j-n/2];
    24         }
    25         if(tot==k)return 1;
    26         if(tot<k)b[cntb++]=tot;
    27     }
    28     sort(b,b+cntb);
    29     for(int i=0;i<cnta;i++)
    30         if(binary_search(b,b+cntb,k-a[i]))return 1;
    31     return 0;
    32 }
    33 int main(){
    34     rep(i,1,18)pow3[i]=pow3[i-1]*3;
    35     int T;
    36     rd(T);
    37     rep(tt,1,T){
    38         int n,k;
    39         rd(n);rd(k);
    40         sum=0;
    41         
    42         for(int i=0;i<n;i++){
    43             rd(v[i]);
    44             sum+=v[i]*2;
    45         }
    46         printf("Case %d: %s
    ",tt,judge(n,k)?"Yes":"No");
    47     }
    48 }
    View Code
    
    
    
     
  • 相关阅读:
    SQL Function(方法)
    SQL Cursor(游标)
    SQL Proc(存储过程)/tran(事物)
    AAABBBBCCCC
    Visual Studio2012中搭建WCF项目
    关于抽象工厂模式
    C#面向对象的学习笔记
    休假回来 更博-MySQL以月为单位的客户综合情况表_20161008
    结合Mysql和kettle邮件发送日常报表_20161001
    MySQL-with rollup函数运用 _20160930
  • 原文地址:https://www.cnblogs.com/KafuuMegumi/p/10090646.html
Copyright © 2011-2022 走看看