总时间限制: 2000ms
单个测试点时间限制: 500ms
内存限制:65536kB
描述
在韩国,有一种小的青蛙。每到晚上,这种青蛙会跳越稻田,从而踩踏稻子。农民在早上看到被踩踏的稻子,希望找到造成最大损害的那只青蛙经过的路径。每只青蛙总是沿着一条直线跳越稻田,而且每次跳跃的距离都相同。
如下图所示,稻田里的稻子组成一个栅格,每棵稻子位于一个格点上。而青蛙总是从稻田的一侧跳进稻田,然后沿着某条直线穿越稻田,从另一侧跳出去
如下图所示,可能会有多只青蛙从稻田穿越。青蛙的每一跳都恰好踩在一棵水稻上,将这棵水稻拍倒。有些水稻可能被多只青蛙踩踏。当然,农民所见到的是图4中的情形,并看不到图3中的直线,也见不到别人家田里被踩踏的水稻,。
根据图4,农民能够构造出青蛙穿越稻田时的行走路径,并且只关心那些在穿越稻田时至少踩踏了3棵水稻的青蛙。因此,每条青蛙行走路径上至少包括3棵被踩踏的水稻。而在一条青蛙行走路径的直线上,也可能会有些被踩踏的水稻不属于该行走路径
①不是一条行走路径:只有两棵被踩踏的水稻;
②是一条行走路径,但不包括(2,6)上的水道;
③不是一条行走路径:虽然有3棵被踩踏的水稻,但这三棵水稻之间的距离间隔不相等。
请你写一个程序,确定:在一条青蛙行走路径中,最多有多少颗水稻被踩踏。例如,图4的答案是7,因为第6行上全部水稻恰好构成一条青蛙行走路径。
输入
从标准输入设备上读入数据。第一行上两个整数R、C,分别表示稻田中水稻的行数和列数,1≤R、C≤5000。第二行是一个整数N,表示被踩踏的水稻数量, 3≤N≤5000。在剩下的N行中,每行有两个整数,分别是一颗被踩踏水稻的行号(1R)和列号(1C),两个整数用一个空格隔开。而且,每棵被踩踏水稻只被列出一次。
输出
从标准输出设备上输出一个整数。如果在稻田中存在青蛙行走路径,则输出包含最多水稻的青蛙行走路径中的水稻数量,否则输出0。
样例输入
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
思路:
1.坐标排序
2.将点两两组合,构成起始的两个点,得出跳跃距离
3.剪枝(关键):两步过后(因为必须踩3棵及以上水稻),超出稻田范围的,剪掉;前一步在稻田内的剪掉(因为跳跃距离太短,青蛙跳不过来)
4.一步一步往下走,若落脚点没有被标记(即此水稻没有被踩过,跳出,进行下次枚举)
5.重复以上过程,直到枚举结束,答案取每次结果的最大值
代码:
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
int n,m,t,mx,my,cx,cy,dx,dy,ans,maxx,flag;
bool vis[5010][5010];
struct ak
{
int x;
int y;
}a[5010];
bool cmp(ak xx,ak yy)
{
if(xx.x==yy.x) return xx.y<yy.y;
else return xx.x<yy.x;
}
bool check(int x,int y)//检测是否在稻田内
{
if(x>=1&&x<=n&&y>=1&&y<=m) return 1;
else return 0;
}
int main( )
{
ios::sync_with_stdio(false);
cin>>n>>m>>t;
for(int i=1;i<=t;i++)
{
cin>>a[i].x>>a[i].y;
vis[a[i].x][a[i].y]=1;//标记此点被踩过
}
sort(a+1,a+t+1,cmp);//坐标排序,先按 x ,再按 y
for(int i=1;i<t;i++)
{
mx=a[i].x,my=a[i].y;
for(int j=i+1;j<=t;j++)
{
cx=a[j].x,cy=a[j].y;//枚举起始两点
dx=cx-mx,dy=cy-my;
if(mx+2*dx<1||mx+2*dx>n) break;
//如果最起始点的 x 坐标加上两步后,超出稻田范围
//直接结束此次枚举,枚举下一个最起始点
//因为,排序按照 x 排序,它不行,他后面的也不行
if(my+2*dy<1||my+2*dy>m) continue;
//如果 y 超出范围,枚举下一个次起始点
if(check(mx-dx,my-dy)) continue;
//判断前一步是否在稻田内
ans=1,flag=0;
while(check(cx,cy))
{
if(vis[cx][cy]==0)
{
flag=1;
//如果落脚点没被踩过,标记,跳出
break;
}
cx+=dx,cy+=dy;
ans++;
}
if(flag==0) maxx=max(maxx,ans);
//最终结果取最大值
}
}
cout<<maxx;
return 0;
}