题目链接:
http://bailian.openjudge.cn/practice/2812
题目:
-
描述
-
在韩国,有一种小的青蛙。每到晚上,这种青蛙会跳越稻田,从而踩踏稻子。农民在早上看到被踩踏的稻子,希望找到造成最大损害的那只青蛙经过的路径。每只青蛙总是沿着一条直线跳越稻田,而且每次跳跃的距离都相同。
如下图所示,稻田里的稻子组成一个栅格,每棵稻子位于一个格点上。而青蛙总是从稻田的一侧跳进稻田,然后沿着某条直线穿越稻田,从另一侧跳出去
如下图所示,可能会有多只青蛙从稻田穿越。青蛙的每一跳都恰好踩在一棵水稻上,将这棵水稻拍倒。有些水稻可能被多只青蛙踩踏。当然,农民所见到的是图4中的情形,并看不到图3中的直线,也见不到别人家田里被踩踏的水稻,。
根据图4,农民能够构造出青蛙穿越稻田时的行走路径,并且只关心那些在穿越稻田时至少踩踏了3棵水稻的青蛙。因此,每条青蛙行走路径上至少包括3棵被踩踏的水稻。而在一条青蛙行走路径的直线上,也可能会有些被踩踏的水稻不属于该行走路径
①不是一条行走路径:只有两棵被踩踏的水稻;
②是一条行走路径,但不包括(2,6)上的水道;
③不是一条行走路径:虽然有3棵被踩踏的水稻,但这三棵水稻之间的距离间隔不相等。
请你写一个程序,确定:在一条青蛙行走路径中,最多有多少颗水稻被踩踏。例如,图4的答案是7,因为第6行上全部水稻恰好构成一条青蛙行走路径。
输入
- 从标准输入设备上读入数据。第一行上两个整数R、C,分别表示稻田中水稻的行数和列数,1≤R、C≤5000。第二行是一个整数N,表示被踩踏的水稻数量, 3≤N≤5000。在剩下的N行中,每行有两个整数,分别是一颗被踩踏水稻的行号(1~R)和列号(1~C),两个整数用一个空格隔开。而且,每棵被踩踏水稻只被列出一次。 输出
- 从标准输出设备上输出一个整数。如果在稻田中存在青蛙行走路径,则输出包含最多水稻的青蛙行走路径中的水稻数量,否则输出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 起步三颗以上,如果没有则输出0 4 解题思路 很明显,用5000乘以5000的稻田存储数据是不现实的,故将点存储进入结构体数组中,枚举不同且不重复的两个点 5 作为进入稻田的第一步和第二步,由此的到该条路径上的方向的每步的距离,如果第一步之前还有符合条件的点,该该路径直接跳过 6 如果第二步的行数加上当前的最大步数倍的距离超出稻田,则直接跳过枚举该第一步,如果第二步的列数超出稻田,则跳过枚举该第二步 7 以上为高效剪枝搜索,如果均满足则进入搜索路径,返回最大步数。 8 9 qsort的用法 10 头文件stdlib 11 qsort(数组起点,元素个数,单个元素的大小( sizeof(数据类型) ),比较函数) 12 13 比较函数 14 int cmp(const void * a, const void * b){ 15 数据类型 *p1,*p2; 16 p1=(强制数据类型转化为对应指针数据类型)a; 17 p2=(强制数据类型转化为对应指针数据类型)b; 18 if(p1->x==p2->x) return (p1->y-p2->y) 19 return (p1->x-p2->x) 20 }//先根据x排,再按照y排 21 22 二分搜索函数的使用 23 头文件stdlib 24 bsearch(&搜索目标,搜索对象起点,对象元素个数,sizeof(数据类型),比较函数); 25 */ 26 #include<stdio.h> 27 #include<stdlib.h> 28 int r,c,n; 29 struct PLANT{ 30 int x,y; 31 }; 32 PLANT plants[5010]; 33 int check(PLANT tmp); 34 int cmp(const void * ele1,const void * ele2); 35 int searchPath(PLANT secPlant,int dx,int dy); 36 int main() 37 { 38 scanf("%d%d%d",&r,&c,&n); 39 int i,j; 40 for(i=0;i<n;i++){ 41 scanf("%d%d",&plants[i].x,&plants[i].y); 42 } 43 qsort(plants,n,sizeof(PLANT),cmp); 44 int dx=0,dy=0,ans=2; 45 PLANT plant; 46 for(i=0;i<n-1;i++){ 47 for(j=i+1;j<n;j++){ 48 dx=plants[j].x-plants[i].x;//不仅仅局限于那8个方向 49 dy=plants[j].y-plants[i].y; 50 51 plant.x=plants[i].x-dx; 52 plant.y=plants[i].y-dy; 53 if(check(plant)) continue;//假设的第一步和第二步是否合法 54 55 if(plants[i].x+ans*dx > r) break;//第一步不合法 56 57 if(plants[i].y+ans*dy > c || plants[i].y+ans*dy < 1) continue;//第二步不合法 58 59 int temp=searchPath(plants[j],dx,dy); 60 if(temp > ans) 61 ans=temp; 62 } 63 } 64 if(ans==2) ans=0; 65 printf("%d\n",ans); 66 return 0; 67 } 68 69 int searchPath(PLANT secPlant,int dx,int dy) 70 { 71 PLANT plant; 72 73 plant.x=secPlant.x+dx; 74 plant.y=secPlant.y+dy; 75 int steps=2; 76 while(check(plant))//合法的路径一定是出界结束而不是界内且搜寻到 77 { 78 if(!bsearch(&plant,plants,n,sizeof(PLANT),cmp)) 79 { 80 steps=0; 81 break; 82 } 83 steps++; 84 plant.x += dx; 85 plant.y += dy; 86 } 87 return steps; 88 } 89 90 int check(PLANT tmp){ 91 if(tmp.x<=r && tmp.x>=1 && tmp.y<=c && tmp.y>=1) 92 return 1; 93 return 0; 94 } 95 96 int cmp(const void * ele1,const void * ele2){ 97 PLANT *p1,*p2; 98 p1=(PLANT *)ele1; 99 p2=(PLANT *)ele2; 100 if(p1->x==p2->x) return (p1->y - p2->y); 101 return (p1->x - p2->x); 102 }