P1930 亚瑟王的宫殿

这题主要是玄学输入+玄学理解+玄学时间复杂度+玄学定理呀QAQ…
至于玄学理解其他题解已经讲得很清楚了呀,主要还是让大家看看我的玄学代码呀QAQ…

//先玄学理解呀
const z:array[1..8,1..2]of -2..2=((1,2),(1,-2),(-1,2),(-1,-2),(2,1),(2,-1),(-2,1),(-2,-1));
var i,j,k,ix,iy:longint;
    m,n,h,t,sum,q:longint;
    kingx,kingy:longint;
    x_ch:array[char]of longint;
    min,p:array[-1..100,-1..100]of longint;
    x,y,u:array[0..10000]of longint;
    main:longint=maxlongint;
    boo:array[-1..100,-1..100]of boolean;
    ans:array[-1..30,-1..50,-1..30,-1..50] of longint;
    s:string;
    ch:char;
function mine(m,n:longint):longint;//min
begin
  if m>n then exit(n) else exit(m);
end;
function max(m,n:longint):longint;//max
begin
  if m>n then exit(m) else exit(n);
end;
procedure find(x1,y1:longint);//以x1,y1为终点呀QAQ
var i,j,k,pd:longint;
begin
  for i:=-2 to 2 do//玄学定理,不知道是谁怎么的呀
  for j:=-2 to 2 do//接国王的位置一定在国王旁边2格内
  if boo[kingx+i,kingy+j] then
  begin
    pd:=0;
    for k:=1 to sum do
    inc(pd,ans[x1,y1,x[k],y[k]]);
    main:=mine(main,pd+max(abs(x1-kingx),abs(y1-kingy)));//当国王直接走到终点
    for k:=1 to sum do
    begin
      main:=mine(main,
      pd-ans[x1,y1,x[k],y[k]]{骑士直接去终点}+ans[kingx+i,kingy+j,x[k],y[k]]{骑士到接的位置}+
      ans[x1,y1,kingx+i,kingy+j]{从接的位置到终点}+max(abs(i),abs(j))){国王到接的位置};//第k个骑士去接国王呀
    end;
  end;
end;
begin
  readln(m,n);
  k:=m;
  m:=n;
  n:=k;
  for ch:='A' to 'Z' do x_ch[ch]:=ord(ch)-ord('A')+1;
  read(ch,k);kingx:=x_ch[ch];kingy:=k;//读入国王位置呀QAQ
  for ix:=1 to m do
  for iy:=1 to n do
  for i:=1 to m do
  for j:=1 to n do ans[ix,iy,i,j]:=123123123;//赋初值
  for ix:=1 to m do//用bfs计算每两个点之间的最短步数,四次居然不超呀,玄学时间复杂度....
  for iy:=1 to n do
  begin
    x[1]:=ix;
    y[1]:=iy;
    u[1]:=0;
    h:=1;
    t:=1;
    for i:=1 to m do
    for j:=1 to n do
    boo[i,j]:=true;
    boo[ix,iy]:=false;
    ans[ix,iy,ix,iy]:=0;
    repeat
      for i:=1 to 8 do
      if boo[x[t]+z[i,1],y[t]+z[i,2]] then
      begin
        inc(h);
        x[h]:=x[t]+z[i,1];
        y[h]:=y[t]+z[i,2];
        u[h]:=u[t]+1;
        ans[ix,iy,x[h],y[h]]:=u[h];//保存最优解呀
        boo[x[h],y[h]]:=false;
      end;
      inc(t);
    until t>h;
  end;
  while not eof do//玄学读入
  begin
    readln(s);//字符串,真麻烦...
    for i:=1 to length(s) do
    begin
      if (s[i] in ['A'..'Z']) then
      begin
        inc(sum);
        x[sum]:=x_ch[s[i]];
        k:=0;
        j:=i+2;
        while (s[j] in ['0'..'9']) and (j<=length(s))do
        begin
          k:=k*10+ord(s[j])-48;
          inc(j);
        end;
        y[sum]:=k;
      end;
    end;
  end;
  if sum=0 then begin write(0); exit; end;
  for i:=1 to m do
  for j:=1 to n do boo[i,j]:=true;
  for i:=1 to m do
  for j:=1 to n do
  begin
    find(i,j);//找最优解呀QAQ
  end;
  write(main);//输出
end.

这是一道玄学难题,难度挺高的,辛苦调了2个小时,,,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值