解题报告 The Rabbits

The rabbits

【题目描述】

众所周知,除了青蛙会跳之外,兔纸也会。

在一片n*m的菜地中,有一些兔纸在活动,每只兔纸可以在菜地中跳来跳去。但是有一些限制条件:

兔纸只能从菜地外跳进菜地内,并且最后一定要跳出去,每只兔纸跳的每步都是等方向、等长的;兔纸在菜地内至少踩到三个点。

这样每只兔纸就在菜地里留下了一条路径。现在告诉你菜地中那些被兔纸踩过(一个点可能被踩不止一次),某人决定捉住一只踩坏菜地块数最多的兔纸惩罚他,来杀一儆百。

【输入格式】

第一行两个整数n,m(1<=n,m<=5000)

第二行一个整数q被踩的点的个数(3<=q<=5 000);

接下来q行每行表示被踩点的横纵坐标。

【输出格式】

踩坏菜地最多的兔纸踩坏的菜地数。

【输入样例】

6 7

14

2 1

6 6

4 2

2 5

2 6

2 7

3 4

6 1

6 2

2 3

6 3

6 4

6 5

6 7

【输出样例】

7

 

其实这个题,最重要的是理解题意。

它的意思是,兔子每一步的步长不定,当每一步都得踩在给出的某一个点上。并且,每一只兔子都跳得是直线,也就是说,在这条直线上,每两个点(要求是已给出的某个点)之间距离相等。

 

注意一点,兔子只踩给出的点,而且一条直线上至少有三个点。

 

然后他的算法很简单,就是枚举,枚举这条直线的开头的两个点。

每次枚举出两个点,看这两个点能不能作为开头的点,也就是说,这两个点所连成的直线上,所有距离相等(为这两个点之间的距离)得点,都是给出的点,并且枚举出的第一个点是开头第一个点(如果不是,就说明这种直线会在后面枚举到,在这里先不用考虑),也就是说,这个点沿直线再往前追溯单位个距离,就一定会出给定的矩形,然后统计这个直线上的距离相等的点,更新答案。

 

注意,可以更新答案的直线上,各个被踩出的点的距离一定相等,并且第一个点沿直线向前追溯这距离和最后一个点沿直线向后追溯这距离,都一定会出了给定的矩形的范围。

 

 

代码 ZSZ

program rabbits;

var map:array[0..5000,0..5000] of boolean;

    l,h:array[0..10000] of longint;

    n,m,i,j,num,sth,stl,lenl,lenh,q,max:longint;

begin

  assign(input,'frog.in');reset(input);

  assign(output,'frog.out');rewrite(output);

  readln(n,m);

  readln(q);

  fillchar(map,sizeof(map),false);

  for i:=1 to q do

    begin

      readln(h[i],l[i]);

      map[h[i],l[i]]:=true;

    end;

  for i:= 1 to q do

    for j:= 1 to q do

      if i<>j then

        begin

          lenh:=h[j]-h[i];

          lenl:=l[j]-l[i];

          if (h[i]-lenh>0)and(l[i]-lenl>0)and(h[i]-lenh<=n)and(l[i]-lenl<=m) then continue;

//如果第一个点往前追溯这距离出不了矩形范围,剪枝

          sth:=h[j];

          stl:=l[j];

          num:=2;

          if (lenh+sth>n)or(lenh+sth<=0)or(lenl+stl>m)or(lenl+stl<=0) then continue;

//如果最后一个点向后追溯这距离就会出了矩形范围,也就是说,这条直线上只有两个点被踩,剪枝

          while (map[lenh+sth][lenl+stl]=true) do

            begin

              inc(num);

              sth:=lenh+sth;

              stl:=lenl+stl;

//跳。。。

              if (lenh+sth>n)or(lenh+sth<=0)or(lenl+stl>m)or(lenl+stl<=0) then break;

//跳出了矩形范围

            end;

          if (sth+lenh>n)or(stl+lenl>m)or(sth+lenh<=0)or(stl+lenl<=0) then

            if (num>=3)and(num>max) then max:=num;

//如果踩着给出的点可以跳出矩形范围,就更新答案。

         end;

  writeln(max);

  close(input);

  close(output);

end.

 

 

原文地址:https://www.cnblogs.com/SueMiller/p/2234509.html