題目描述:http://poj.org/problem?id=1054
本題使用枚舉的思想。但是單純枚舉解得範圍太大,我們需要在對可能的範圍進行剪枝。我們可以先選中一個點作爲起始點,另一個點做第二個點,這樣就可以確定一條直線。再對這條直線是否符合剪枝條件進行考察,先來可以下剪枝的條件有哪些:
1、既然選中了起始點,那麼根據其與第二個點的步長,可以知道上一步一定是在田外的,否則就不能成爲起始點。
2、按題目中要求,你只關心大於等於三條稻子被壓倒的路徑,那麼如果第三個點已經在田外,則也不符合情況。
3、如果從第一個點開始,走當前maxSteps-1步,到了田外面,那麼這條路徑一定也是不符合情況的(maxSteps爲當前最長路徑)。
基本思路:
1、寫一個Plant類,代表被踩到的稻子。其中成員變量包括此稻子的x座標和y座標。
2、對被踩到的稻子按照先x軸再y軸的標準,從小到大排序。從而後面再確定某一步是否被踩到時,可以使用二分查找。
3、對第一個點和第二個點的組合進行枚舉,在枚舉過程中進行剪枝。
AC代碼如下:
//POJ 1054
package week1;
import java.util.*;
public class The_Troublesome_frog {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int r = sc.nextInt();
int c = sc.nextInt();
int n = sc.nextInt();
Plant[] plants = new Plant[n];
//初始化
for(int i=0; i<n; i++){
plants[i] = new Plant();
plants[i].x = sc.nextInt();
plants[i].y = sc.nextInt();
}
Arrays.sort(plants);
int maxSteps = 2;
//選擇plant[i]爲第一個點,plants[j]爲第二個點
for(int i=0; i<n;i++){
for(int j=i+1; j<n; j++){
int dx = plants[j].x - plants[i].x;
int dy = plants[j].y - plants[i].y;//在x和y方向上求得青蛙每一步的長度
int px = plants[i].x - dx;
int py = plants[i].y - dy;//求按照此步長,第一步之前的一步的位置
if(px >= 1 && px <= r && py >= 1 && py <= c)
continue;
//如果第一點的前一點在稻田內,說明第二點選的不合適,換一個點做第二點
int xMax = plants[i].x + (maxSteps - 1) * dx;
if(xMax > r)
break;
//未達到目前最長步數-1就出了稻田,說明這條路無法成爲當前最長
//因爲x是進過排序的,因此換第二個點只能使得出稻田更快,因此此時要換第一個點
int yMax = plants[i].y + (maxSteps - 1) * dy;
if(yMax > c || yMax < 1)
continue;
//Y方向過早越界,換第二個點
int steps = searchPath(plants[j], plants, dx, dy, r, c);
if (steps > maxSteps){
maxSteps = steps;
}
}
}
if(maxSteps == 2) maxSteps = 0;
System.out.println(maxSteps);
sc.close();
}
public static int searchPath(Plant secPlant, Plant[] plants, int dx, int dy, int r, int c){
Plant tmp = new Plant();//表示當前位置
tmp.x = secPlant.x + dx;
tmp.y = secPlant.y + dy;
int steps = 2;
while(tmp.x <= r && tmp.x >=1 && tmp.y <= c && tmp.y >= 1){
//當下一步在稻田內時,查找下一步的座標是否在Plants[]中
int index = Arrays.binarySearch(plants, tmp);
if( index < 0){
steps = 0;
break;
}
steps++;
tmp.x += dx;
tmp.y += dy;
}
return steps;
}
}
class Plant implements Comparable<Plant>{
int x;
int y;
public Plant(){
this.x = 0;
this.y = 0;
}
public int compareTo(Plant p) {
if(this.x > p.x){
return 1;
}
else{
if(this.x < p.x) return -1;
else{
if(this.y > p.y) return 1;
else
{
if(this.y < p.y)
return -1;
else return 0;
}
}
}
}
}