POJ 1054 Java: The Troublesome Frog

題目描述: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;
				}
			}
		}
	}
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章