嗯,今天上午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.