考察要点:优化判断条件,枚举,
技巧:qsort 和 bsearch 库函数的使用
解题思路:
(1) 任何一条穿越稻田的青蛙路径L,至少包括3 棵被踩踏的水稻。假设其中前两
棵被踩踏的水稻分别是(X1,Y1)、(X2,Y2),那么:
* 令 dx=X2-X1、dy=Y2-Y1;X0=X1-dx、Y0=Y1- dy;X3=X2 + dx、Y3=Y2 + dy
* (X0,Y0)位于稻田之外,青蛙从该位置经一跳后进入稻田、踩踏位置(X1,Y1)上的水稻
*(X3,Y3)位于稻田之内,该位置是L 上第3 棵被青蛙踩踏的水稻
* Xi=X0 + idx、Yi=Y1 + idy(i3),如果(Xi,Yi)位于稻田之内,则(Xi,Yi)上的水稻必被
青蛙踩踏
(2) 从被踩踏的水稻中选择两棵(X1,Y1)、(X2,Y2)。判断它们是否
能够作为一条青蛙路径上最先被踩踏的两颗水稻。(X1,Y1)、(X2,Y2)唯一确定了蛙跳的方
向和步长,从(X2,Y2)开始,沿着这个方向和步长在稻田内走。每走一步,判断所到达位置
上(X,Y)的水稻是否被踩踏,直到走出稻田为止。
(3) 用一个 PLANT 型的数组plants[5001]表示全部被踩踏的水稻
*将 plants 中的元素按照行/列序号的升序(或者降序)排列
*采用二分法查找 plants 中是否有值为(X,Y)的元素:将(X,Y)与plants 中间的元素比较,
(1)相等,表明找到了元素;(2)比plants 中间元素的小,继续在plants 的前半部寻找;(3)
比plants 中间元素的大,继续在plants 的后半部寻找。
/** POJ 1054 **/
#include <stdio.h>
#include <stdlib.h>
int r ,c,n;//行、列、和被踩水稻数
struct PLANT
{
int x;
int y;
};
PLANT plants[5001];
PLANT plant;
int cmp(const void *elem1,const void *elem2);//定义比较函数 对水稻行列进行排序
int Binsearch(PLANT secPant,int dx,int dy); //在plants中查找是否有(X,Y)
int main()
{
freopen("in.txt","r",stdin);
int i,j,dx,dy,px,py,steps,max=2;
scanf("%d%d",&r,&c);
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d%d",&plants[i].x,&plants[i].y);
qsort(plants,n,sizeof(PLANT),cmp); //排序
for(i=0;i<n-2;i++)
for(j=i+1;j<n-1;j++)
{
dx = plants[j].x - plants[i].x; //计算被踩的水稻水平距离
dy = plants[j].y - plants[i].y; //计算被踩的水稻水平距离
px = plants[i].x - dx; //计算下一棵被踩水稻的横坐标
py = plants[i].y - dy; //计算下一棵被踩水稻的纵坐标
if(px<=r&&px>=1&&py<=c&&py>=1) //如果没有越界
continue;
if((plants[i].x + max *dx)>r) //越界则 排除此情况
break;
py = plants[i].y +max *dy;
if(py>c||py<1)
continue;
steps = Binsearch(plants[j],dx,dy); //在plants数组中查找是否存在计算出的坐标
if(steps>max) max = steps; //更新最大被踩水稻棵数
}
if(max == 2) max = 0; //至少3棵
printf("%d\n",max);
return 0;
}
int cmp(const void *elem1,const void *elem2)
{
PLANT *p1,*p2;
p1 = (PLANT *)elem1;
p2 = (PLANT *)elem2;
if(p1->x == p2->x) return p1->y -p2->y; //按行号或列号升序排列
return p1->x - p2->x;
}
int Binsearch(PLANT secPant,int dx,int dy)
{
PLANT plant;
int steps;
plant.x = secPant.x + dx;
plant.y = secPant.y + dy;
steps = 2; //初始值 为2;
while(plant.x<=r&&plant.x>=1&&plant.y<=c&&plant.y>=1)
{
if(!bsearch(&plant,plants,n,sizeof(PLANT),cmp)) //如果查找不到(X,Y)
{
steps = 0;
break ;
}
plant.x += dx; //计算出下一颗的坐标
plant.y += dy;
steps++; //查找成功 ,棵数增加
}
return (steps);
}