题意:题目给出两列数,为了使两列数的和之间的差距(gap)变小,可以交换对应位置的数字,
求出当gap最小的时候,最少的交换次数.
分析:用f[i,j]表示处理完前i对数,差为j的最少交换次数.
注意到f[i]只跟f[i-1]有关,可以用滚动数组.转移类似于填表.
code:
var a,b,d:array[0..1001] of longint; f:array[0..1,-6000..6000] of longint; g:array[0..1,-6000..6000] of boolean; n,i,j,pre,now:longint; function min(a,b:longint):longint; begin if a>b then exit(b); exit(A); end; begin readln(n); for i:=1 to n do begin readln(a[i],b[i]); d[i]:=a[i]-b[i]; end; pre:=0; now:=1; f[pre,d[1]]:=0; g[pre,d[1]]:=true; f[pre,-d[1]]:=1; g[pre,-d[1]]:=true; for i:=1 to n-1 do begin fillchar(f[now],sizeof(f[now]),0); fillchar(g[now],sizeof(g[now]),0); for j:=-6000 to 6000 do if g[pre,j] then begin if abs(j+d[i+1])<=6000 then if not g[now,j+d[i+1]] then begin f[now,j+d[i+1]]:=f[pre,j]; g[now,j+d[i+1]]:=true; end else f[now,j+d[i+1]]:=min(f[pre,j],f[now,j+d[i+1]]); if abs(j-d[i+1])<=6000 then if not g[now,j-d[i+1]] then begin f[now,j-d[i+1]]:=f[pre,j]+1; g[now,j-d[i+1]]:=true; end else f[now,j-d[i+1]]:=min(f[pre,j]+1,f[now,j-d[i+1]]); end; pre:=1-pre; now:=1-now; end; for i:=0 to 6000 do if g[pre,i] then break; for j:=0 downto -6000 do if g[pre,j] then break; if abs(j)<i then writeln(f[pre,j]) else writeln(f[pre,i]); end.