1. 程式人生 > >2812 惱人的青蛙(暴力搜索時根據問題優化判斷條件以加快搜索速度)

2812 惱人的青蛙(暴力搜索時根據問題優化判斷條件以加快搜索速度)

對象 sea 轉化 列數 函數 pla ecp 間隔 problem

題目鏈接:

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 }

2812 惱人的青蛙(暴力搜索時根據問題優化判斷條件以加快搜索速度)