题目大意:一个r行c列的农田,有n个脚印在农田上。如果一连串脚印满足是一条直线,并且等间距分布,并且是从农田外跳入并跳出农田外,则认为这一串脚印为青蛙的一条路径。求所有路径中的最长步数,我们只关心步数大于等于3的路径。
思路:枚举两个点,构成一条直线,判断这条直线是否满足条件,若满足,则记录步数,取所有路径的步数的最大值。
几点优化和剪枝:
(1)首先将所有脚印按r从小到大排列,如果r相同,则按c从小到大排列,这是为后面的剪枝做准备。
(2)如果起点不是从农田外跳入,剪枝
(3)如果起点经过当前最大步数后已经跳出农田外,剪枝
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;
struct Pos
{
int row,column;
bool operator< (const Pos a) const
{
if (a.row==row)
return column<a.column;
return row<a.row;
}
}flattened_pos[5005];
bool flattened[5005][5005],is_path;
int row,column,flatten_num,ans;
int main(int argc, char** argv)
{
int i,j,dx,dy,cnt,tmp_row,tmp_column;
while (scanf("%d%d",&row,&column)==2)
{
memset(flattened,false,sizeof(flattened));
scanf("%d",&flatten_num);
for (i=1; i<=flatten_num; i++)
{
scanf("%d%d",&flattened_pos[i].row,&flattened_pos[i].column);
flattened[flattened_pos[i].row][flattened_pos[i].column]=true;
}
sort(flattened_pos+1,flattened_pos+1+flatten_num);
ans=2;
for (i=1; i<flatten_num; i++)
{
for (j=i+1; j<=flatten_num; j++)
{
dx=flattened_pos[j].row-flattened_pos[i].row;
dy=flattened_pos[j].column-flattened_pos[i].column;
if (flattened_pos[i].row+(ans-1)*dx>row || flattened_pos[i].row+(ans-1)*dx<1 || flattened_pos[i].column+(ans-1)*dy>column || flattened_pos[i].column+(ans-1)*dy<1)
continue;
if (flattened_pos[i].row-dx>=1 && flattened_pos[i].row-dx<=row && flattened_pos[i].column-dy>=1 && flattened_pos[i].column-dy<=column)
continue;
tmp_row=flattened_pos[j].row;
tmp_column=flattened_pos[j].column;
is_path=true;
for (cnt=2;; cnt++)
{
tmp_row+=dx;
tmp_column+=dy;
if (tmp_row>row || tmp_row<1 || tmp_column>column || tmp_column<1)
break;
else if (flattened[tmp_row][tmp_column]==false)
{
is_path=false;
break;
}
}
if (is_path && cnt>ans)
ans=cnt;
}
}
if (ans==2)
printf("0\n");
else
printf("%d\n",ans);
}
return 0;
}