田忌赛马(Tyvj1048)

本文通过动态规划算法解决经典博弈问题——齐王赛马。首先对马匹进行快排,然后定义状态转移方程,计算最优解。通过程序实现,最终输出赢得比赛的最优策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

算法: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;
 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值