首页 > 代码库 > CODEVS2144 砝码称重2 (哈希表)

CODEVS2144 砝码称重2 (哈希表)

由于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.

 

CODEVS2144 砝码称重2 (哈希表)