算法练习(21):Frog Jump

算法练习(21):Frog Jump_第1张图片

题意:给出石头的位置,然后青蛙每一跳的距离a和上一跳距离k满足(k==a||k==a-1||k==a+1),第一个石头是位置0,第一跳只能距离为1.

分析与思路:这个题目用遍历搜索所有的路线是肯定可以做的,但是简单的遍历会超时,我用的方法是深度优先遍历同时排除掉不可能的情况。我用一个数据结构step来保存当前位置以及跳到这里的上一跳距离,我用一个优先队列(位置靠后的优先)保存所有出现过的step,同时要排除一些不可能情况,我排除的不可能情况在注释中已表明。

代码:

class step {//每一步的有关数据
public:
	int nowStone = 0;
	int lastdis = 0;
	step(int a, int b) {
		lastdis = b;
		nowStone = a;
	}
};
struct cmp {//优先队列的比较函数
	bool operator()(const step a, const step b) {
		return a.nowStone < b.nowStone;
	}
};
const int MAXSTEP = pow(2, 31) / 1000;
/*最长步距,最多1100个数据,最大值是pow(2, 31),所以满足条件的情况不可能有一步会超过这个值,
因为必须从一开始的1慢慢增到pow(2, 31),最少的步长要为pow(2, 31) / 1100,所以不妨放到除以1000,*/
class Solution {
public:
	bool canCross(vector& stones) {
		if (stones.size() == 2) {//特殊情况
			if (stones[0] == 0 && stones[1] == 1) return true;
			else return false;
		}
		priority_queue,cmp> steps;
		steps.push(step(1, 1));//初始化
		int maxdis = 1;//记录在队列中出现过的满足条件的最长步距
		while (!steps.empty()) {
			step nowsteps = steps.top();
			steps.pop();
			int count = 3;//每一步的下一步最多有三种满足条件的情况
			for (int i = nowsteps.nowStone+1; i < stones.size(); i++) {
				if (stones[i] - stones[nowsteps.nowStone] > MAXSTEP) return false;//防止出现极端值
				if (stones[i] - stones[nowsteps.nowStone] > nowsteps.lastdis + 1) break;
				//出现了超过这个值以后的情况都不用考虑能作为当前步的下一步
				if (stones[i] - stones[nowsteps.nowStone] > maxdis + 1) return false;
				//出现了超过队列中出现的最长步距则说明不可能还能延续下去,可以终止了
				if (stones[i]-stones[nowsteps.nowStone] == nowsteps.lastdis
					|| stones[i]-stones[nowsteps.nowStone] == nowsteps.lastdis + 1
					|| stones[i]-stones[nowsteps.nowStone] == nowsteps.lastdis - 1) {
					count--;
					if (stones[i] - stones[nowsteps.nowStone] > maxdis) maxdis = stones[i] - stones[nowsteps.nowStone];//更新
					steps.push(step(i,stones[i]-stones[nowsteps.nowStone]));
					if (i == stones.size()-1) return true;//找到目标
					if (count == 0) break;
				}
			}
		}
		return false;
	}
};


你可能感兴趣的:(算法练习)