首页 > 技术文章 > 2812 恼人的青蛙(暴力搜索时根据问题优化判断条件以加快搜索速度)

wenzhixin 2018-03-01 15:02 原文

题目链接:

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 }

 

推荐阅读