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;
				}
			}
		}
	}
}


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