题目描述

现有n个砝码,重量分别为 a_iai,在去掉 mm 个砝码后,问最多能称量出多少不同的重量(不包括 00)。

请注意,砝码只能放在其中一边。

输入格式

第 11 行为有两个整数 nn 和 mm,用空格分隔。

第 22 行有 nn 个正整数 a_1, a_2, a_3,\ldots , a_na1,a2,a3,,an,表示每个砝码的重量。

输出格式

仅包括 11 个整数,为最多能称量出的重量数量。

输入输出样例

输入 #1<button class="copy&#45;btn lfe&#45;form&#45;sz&#45;middle" data&#45;v&#45;370e72e2="" data&#45;v&#45;52f2d52f="" type="button">复制</button>
3 1
1 2 2
输出 #1<button class="copy&#45;btn lfe&#45;form&#45;sz&#45;middle" data&#45;v&#45;370e72e2="" data&#45;v&#45;52f2d52f="" type="button">复制</button>
3

 

 

思路

  搜索出抛弃个数为m的所有组合,在dfs的过程中给不用的砝码打上标记,然后利用01背包的方式求解最大的不同数字的组合即可。

  这题不加优化,稳妥一点从5000种枚举到0,跑了将近700ms,如果随时记录可用砝码重量的最大值来优化这个过程,就像题解中那样,只要跑100ms左右。

 

CODE

 

 

#include  < bits/stdc++.h >
#define  dbg( x ) cout  <<  #x  <<  " = "  << x  << endl
#define  eps  1 e - 8
#define  pi  acos( - 1.0 )

using  namespace std ;
typedef  long  long LL ;

const  int inf  =  0x 3f3f3f3f ;

template < class T > inline  void  read(& res )
{
     char c ;T flag = 1 ;
     while((c = getchar()) < ' 0 ' ||c > ' 9 ' )if(c == ' - ' )flag =- 1 ;res =c - ' 0 ' ;
     while((c = getchar()) >= ' 0 ' &&c <= ' 9 ' )res =res * 10 +c - ' 0 ' ;res *=flag ;
}

namespace _buff  {
     const  size_t BUFF  =  1  <<  19 ;
     char  ibuf [BUFF ],  *ib  = ibuf ,  *ie  = ibuf ;
     char  getc()  {
         if  (ib  == ie )  {
            ib  = ibuf ;
            ie  = ibuf  +  fread(ibuf ,  1 , BUFF , stdin );
         }
         return ib  == ie  ?  - 1  :  *ib ++ ;
     }
}

int  qread()  {
     using  namespace _buff ;
     int ret  =  0 ;
     bool pos  =  true ;
     char c  =  getc();
     for  (;  (<  ' 0 '  || c  >  ' 9 ' )  && c  !=  ' - ' ; c  =  getc())  {
         assert( ~c );
     }
     if  (==  ' - ' )  {
        pos  =  false ;
        c  =  getc();
     }
     for  (; c  >=  ' 0 '  && c  <=  ' 9 ' ; c  =  getc())  {
        ret  =  (ret  <<  3 )  +  (ret  <<  1 )  +  (^  48 );
     }
     return pos  ? ret  :  -ret ;
}

int n , m ;
int  a [ 50 ];
bool  vis [ 50 ];
int  f [ 50 ];
int maxx  =  0 ;
int maxn  =  0 ;

int  check()  {
     int num  =  0 ,  f [ 20007 ]  =  { 0 };
     f [ 0 ]  =  1 ;
     for  (  int i  =  1 ; i  <= n ;  ++)  {
         if( vis [i ])
             continue;
         for  (  int j  = maxx ; j  >=  0 ;  --)  {
             if( f [j ])  {
                 f [+  a [i ]]  =  1 ;
             }
         }
     }
     for  (  int i  =  1 ; i  <= maxx ;  ++)  {
         if( f [i ])  {
             ++num ;
         }
     }
     return num ;
}

void  dfs( int  id ,  int  sum )  {
     if(check()  <= maxn )  {
         return;
     }
     if(sum  == m  +  1 )  {
         int k  =  check();
        maxn  =  max(maxn , k );
         return;
     }
     for  (  int i  = id  +  1 ; i  <= n ;  ++)  {
         vis [i ]  =  1 ;
        maxx  -=  a [i ];
         dfs(i , sum  +  1 );
         vis [i ]  =  0 ;
        maxx  +=  a [i ];
     }
}

int  main()
{
     read(n );
     read(m );
     for  (  int i  =  1 ; i  <= n ;  ++)  {
         read( a [i ]);
        maxx  +=  a [i ];
     }
     sort(+  1 , a  + n  +  1 );
     dfs( 0 ,  1 );
    cout  << maxn  << endl ;
     return  0 ;
}