算法:DP
经典博弈问题,所谓赢得比赛,无非就是快马赢了慢马,而最好的贪心策略就是让其中一方的最慢的马输给对手最快的马,而齐王和田忌的出马都是无序的,因此我们先从大到小快排一遍,这样我们就
将这个问题进行了转化,每次选马无非就是从头取或者从尾取,到此,思路已经十分清晰,本题的转移方程非常类似于矩阵取数游戏。(设f[i,j]表示前i匹马从前面取了j匹。)
program P1048;
const
maxn=1000;
var
n,ans:longint;
a,b:array [0..maxn] of longint;
cost,f:array [0..maxn,0..maxn] of longint;
procedure qsort1(l,r:longint);
var
i,j,m,t:longint;
begin
i:=l;
j:=r;
m:=a[(l+r) shr 1];
repeat
while a[i]>m do inc(i);
while a[j]<m do dec(j);
if i<=j then
begin
t:=a[i];
a[i]:=a[j];
a[j]:=t;
inc(i);
dec(j);
end;
until i>j;
if i<r then qsort1(i,r);
if l<j then qsort1(l,j);
end;
procedure qsort2(l,r:longint);
var
i,j,m,t:longint;
begin
i:=l;
j:=r;
m:=b[(l+r) shr 1];
repeat
while b[i]>m do inc(i);
while b[j]<m do dec(j);
if i<=j then
begin
t:=b[i];
b[i]:=b[j];
b[j]:=t;
inc(i);
dec(j);
end;
until i>j;
if i<r then qsort2(i,r);
if l<j then qsort2(l,j);
end;
procedure init;
var
i,j:longint;
begin
ans:=-maxlongint;
readln(n);
for i:=1 to n do read(a[i]);
readln;
qsort1(1,n);
for i:=1 to n do read(b[i]);
qsort2(1,n);
for i:=1 to n do
begin
for j:=1 to n do
begin
if a[i]=b[j] then cost[i,j]:=0;
if a[i]>b[j] then cost[i,j]:=200;
if a[i]<b[j] then cost[i,j]:=-200;
end;
end;
end;
function max(x,y:longint):longint;
begin
if x>y then exit(x) else exit(y);
end;
procedure main;
var
i,j:longint;
begin
fillchar(f,sizeof(f),200);
f[0,0]:=0;
for i:=1 to n do
begin
for j:=0 to i do
begin
if j=0 then f[i,j]:=f[i-1,j]+cost[n-(i-j)+1,i]{如果不从前面取,一定是从后面开始取的。}
else f[i,j]:=max(f[i-1,j-1]+cost[j,i],f[i-1,j]+cost[n-(i-j)+1,i]);{开始写反了,因为要比的是齐王的第i匹马,然后田忌做决定,所以是田忌的那匹马于齐王的第i匹马比较。}
end;
end;
end;
procedure print;
var
i:longint;
begin
for i:=0 to n do if f[n,i]>ans then ans:=f[n,i];
writeln(ans);
end;
begin
assign(input,'P1048.in'); reset(input);
assign(output,'P1048.out'); rewrite(output);
init;
main;
print;