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