POJ1015 Jury Compromise——DP——被某些人害苦了!!!

水水的DP,网上居然有人说200*400*20会爆内存~于是想了一个滚动数组的,但是状态记录就不好办了,后来才发现200*400*20是没问题的……

状态转移方程:

dp[i][j]表示选出i个人、两方差值为j的时候两方价值和的最大值

dp[i][j]=max{ dp[i-1][j-p[i]+d[i]]+p[i]+d[i] }

记录路径的话,直接记录并倒推即可……

参考代码:

program poj1015;//By_Thispoet

const

	maxn=4000;

var

	i,j,k,m,n,p,test			:longint;

	mini,maxi					:longint;

	f							:array[0..200,-maxn..maxn]of longint;

	a,b							:array[0..maxn]of longint;

	ans							:array[0..20,-maxn..maxn,0..20]of longint;

	

function min(i,j:longint):longint;

begin

	if i<j then exit(i);exit(j);

end;



function max(i,j:longint):longint;

begin

	if i>j then exit(i);;exit(j);

end;



begin

	readln(n,m);test:=0;

	while not ((n=0)and(m=0)) do begin

		inc(test);

		for i:=1 to n do readln(a[i],b[i]);

		mini:=0;maxi:=0;fillchar(f,sizeof(f),128);f[0,0]:=0;

		for i:=1 to n do begin

			p:=a[i]-b[i];

			if p>=0 then begin

				for j:=min(i,m) downto 1 do

					for k:=maxi downto mini do

						if f[j-1,k]>=0 then if f[j-1,k]+a[i]+b[i]>f[j,k+p] then begin

							f[j,k+p]:=f[j-1,k]+a[i]+b[i];

							move(ans[j-1,k,0],ans[j,k+p,0],4*j);ans[j,k+p,j]:=i;

						end;

			maxi:=maxi+p;

			end else begin

				for j:=min(i,m) downto 1 do

					for k:=mini to maxi do

						if f[j-1,k]>=0 then if f[j-1,k]+a[i]+b[i]>f[j,k+p] then begin

							f[j,k+p]:=f[j-1,k]+a[i]+b[i];

							move(ans[j-1,k,0],ans[j,k+p,0],4*j);ans[j,k+p,j]:=i;

						end;

				mini:=mini+p;

			end;

		end;

		for i:=0 to max(maxi,-mini) do 

			if (f[m,i]>=0)and(f[m,i]>=f[m,-i]) then begin

				j:=i;break;

			end else if f[m,-i]>=0 then begin

				j:=-i;break;

			end;

		writeln('Jury #',test);k:=j;

		writeln('Best jury has value ',(f[m,j]+j)>>1,' for prosecution and value ',(f[m,j]-j)>>1,' for defence:');

		for i:=1 to m do write(' ',ans[m,k,i]);writeln;writeln;

		readln(n,m);

	end;

end.

 

你可能感兴趣的:(Promise)