嗯,今天上午ywt命令我写二进制压位背包,于是今天下午犯了一下午的sx,然后终于做出来了。布尔型背包压位存储不会写,拿来练手。WA了N次,然后写不加优化的,还是WA,最后发现自己把二进制拆分边界条件写错了……看完lyd的题解,发现还有一种不用单调队列、不用压位、但是空间花销比较大的简单算法,贴个传送门吧:http://poj.org/showmessage?message_id=156751
我的代码:
Program Cash_Machine;//By_Thispoet Var i,j,k,m,n,p,q,v,c,a,b :Longint; f :Array[-1..4000]of Int64; Function Getans():Longint; var i:Longint; begin for i:=m downto 0 do begin if ((f[i div 30] and (1<<(i mod 30)))>0) then exit(i); end; end; BEGIN repeat read(m,n); fillchar(f,sizeof(f),0); f[0]:=1; for i:=1 to n do begin read(c,v); k:=1; while k<=(c>>1) do begin q:=((m div 30)*30-v*k);a:=q div 30; b:=(q+30)mod 30; for j:=(m div 30)downto((v*k) div 30) do begin if q>=0 then begin f[j]:=f[j] or (f[a]>>(b)); f[j]:=f[j] or (f[a+1]<<(30-b)); f[j]:=f[j] and ((1<<30)-1); end else begin f[j]:=f[j] or (f[0]<<(30-b)); f[j]:=f[j] and ((1<<30)-1); end; dec(a); end; k:=k<<1; end; dec(k);k:=c-k; q:=((m div 30)*30-v*k);a:=q div 30; b:=(q+30)mod 30; for j:=(m div 30)downto ((v*k) div 30) do begin if q>=0 then begin f[j]:=f[j] or (f[a]>>b); f[j]:=f[j] or (f[a+1]<<(30-b)); f[j]:=f[j] and ((1<<30)-1); end else begin f[j]:=f[j] or (f[0]<<(30-b)); f[j]:=f[j] and ((1<<30)-1); end; dec(a); end; end; writeln(Getans()); until seekeof; END.