由于m很大,所以不能使用DP。
注意到n≤30,直接暴力2^n会TLE。
所以,将砝码平均分成两份,对一份进行一次暴力,用哈希表存下可能的结果。
对下一份再进行一次暴力,在哈希表中搜索剩余的砝码重量是否存在,若存在则更新答案。
输出最小答案即可。
Program CODEVS2144; const maxn=100; maxh=100007; var a:array[0..maxn] of longint; n,i,ans:longint; m:int64; h:array[0..maxh,1..2] of longint; procedure insert(x,y:longint); var hash:longint; begin hash:=x mod maxh; while (h[hash,1]<>-1) and (h[hash,1]<>x) do hash:=(hash+1) mod maxh; if h[hash,1]=-1 then begin h[hash,1]:=x; h[hash,2]:=y; end else if y<h[hash,2] then h[hash,2]:=y; end; function find(x:longint):longint; var hash:longint; begin hash:=x mod maxh; while (h[hash,1]<>-1) and (h[hash,1]<>x) do hash:=(hash+1) mod maxh; if h[hash,1]=-1 then exit(0) else exit(h[hash,2]); end; procedure dfs(x:longint;sum:int64;num:longint); begin if sum>m then exit; if x=n div 2+1 then begin insert(sum,num); exit; end; dfs(x+1,sum,num); dfs(x+1,sum+a[x],num+1); end; procedure work(x:longint;sum:int64;num:longint); var j:longint; begin if sum>m then exit; if x=n+1 then begin if sum=m then begin if num<ans then ans:=num; exit; end; j:=find(m-sum); if j<>0 then begin if j+num<ans then ans:=j+num; end; exit; end; work(x+1,sum,num); work(x+1,sum+a[x],num+1); end; begin for i:=1 to maxh do h[i,1]:=-1; readln(n,m); for i:=1 to n do readln(a[i]); ans:=maxn; dfs(1,0,0); work(n div 2+1,0,0); writeln(ans); end.