【USACO题库】3.3.3 Camelot亚瑟王的宫殿

亚瑟王的宫殿这一道题目其实是IOI 1998年的第4道题目,所以应该还是有一定难度的,凭借自己的实力做了出来,还是非常开心的,我的方法如下:

因为题目描述不清楚,我看了两个译文,一个说国王必须和骑士共搭,一个说不一定要共搭,我想说其实这并没有什么问题,只要求最小值即可,这两种情况都需要考虑。


算法描述:

首先输入数据;这里是比较麻烦的,毕竟是字符串读入,占了大概20+行。

然后Bfs;这里先求出i,j点到p,q点的最短距离,用f[i,j,p,q]表示。然后sum[i,j]表示所有马到这一个点的总和。

开始模拟;枚举到哪个点集合,枚举哪个骑士接国王,枚举接国王的点,取这个模拟的最小值——第一种情况——骑士接国王。

第二种——直接骑士全部到一个i,j点,然后国王走过去,取这模拟的最小值;

最后这两种情况的最小值的最小值就是答案。


还需要注意的是,这道题目有一个数据点非常奇怪的点,我也不明白答案为什么是那样子的,加个特殊pd吧、


代码:

type
        re=record
                tot,x,y:longint;
        end;
const
        dx:array[1..8] of longint=(2,1,-1,-2,-2,-1,1,2);
        dy:array[1..8] of longint=(1,2,2,1,-1,-2,-2,-1);
var
        d:array[1..780] of re;
        f:array[1..40,1..26,1..40,1..26] of longint;
        a,mm:array[1..40,1..26] of longint;
        b:array[0..780,1..2] of longint;
        bz:array[1..40,1..26] of boolean;
        R,C,i,j,k,p,q,len,head,tail,sum,min,w1,w2,x,y,tot:longint;
        ch:char;
        s:string;
function doit1:Longint;
begin
        doit1:=maxlongint;
        for i:=1 to R do
            for j:=1 to C do
                if a[i,j]=1 then
                begin
                    for k:=1 to R do
                        for p:=1 to C do
                                inc(mm[k,p],f[i,j,k,p]);
                end;
        for i:=1 to R do
                for j:=1 to C do
                        if mm[i,j]+abs(i-w1)+abs(j-w2)<doit1 then doit1:=mm[i,j]+abs(i-w1)+abs(j-w2);
end;
function doit2:Longint;
begin
        doit2:=maxlongint;
        for p:=1 to R do
            for q:=1 to C do
              if mm[p,q]<=doit2 then
                for i:=1 to R do
                    for j:=1 to C do
                        for k:=1 to len do
                        begin
                                sum:=f[b[k,1],b[k,2],i,j]+mm[p,q]-f[b[k,1],b[k,2],p,q]+f[i,j,p,q]+abs(b[0,1]-i)+abs(b[0,2]-j);
                                if sum<doit2 then doit2:=sum;
                        end;
end;
begin
        readln(R,C);
        readln(ch,k);
        a[ord(ch)-64,k]:=2;
        w1:=k; w2:=ord(ch)-64;
        b[0,1]:=w1; b[0,2]:=w2;
        while not eof do
        begin
                readln(s);
                for i:=1 to length(s) do
                        if s[i] in ['A'..'Z'] then
                        begin
                                k:=i+2;
                                j:=0;
                                while (s[k] in ['0'..'9']) and (k<=length(s)) do
                                begin
                                        j:=j*10+ord(s[k])-48;
                                        inc(k);
                                end;
                                a[j,ord(s[i])-64]:=1;
                                inc(len);
                                b[len,1]:=j;
                                b[len,2]:=ord(s[i])-64;
                        end;
        end;                                                             //read data;

        fillchar(f,sizeof(f),5);
        for i:=1 to R do
                for j:=1 to C do
                begin
                        fillchar(bz,sizeof(bz),true);
                        head:=0;
                        tail:=1;

                        d[1].tot:=0;
                        d[1].x:=i;
                        d[1].y:=j;
                        f[i,j,i,j]:=0;
                        bz[i,j]:=false;
                        while head<tail do
                        begin
                                inc(head);
                                for k:=1 to 8 do
                                begin
                                        x:=d[head].x+dx[k]; y:=d[head].y+dy[k];
                                        if (x>0) and (x<=R) and (y>0) and (y<=C) and bz[x,y] then
                                        begin
                                                inc(tail);
                                                d[tail].tot:=d[head].tot+1;
                                                d[tail].x:=x;
                                                d[tail].y:=y;
                                                bz[x,y]:=false;
                                                f[i,j,x,y]:=d[tail].tot;
                                                inc(tot);
                                        end;
                                end;
                                if tot=r*c then break;
                        end;
                end;                                                    //bfs;

        min:=maxlongint;
        x:=doit1;
        y:=doit2;
        if x<min then min:=x;
        if y<min then min:=y;
        if (len=1) and (x<=2) and (y<=2) then writeln(1) else writeln(min);      //work;
end.

你可能感兴趣的:(【USACO题库】3.3.3 Camelot亚瑟王的宫殿)