[LeetCode 403]Frog Jump (宽度优先搜索BFS)

来源:互联网 发布:浙江大学翁恺 c语言pat 编辑:程序博客网 时间:2024/05/29 12:30

A frog is crossing a river. The river is divided into x units and at each unit there may or may not exist a stone. The frog can jump on a stone, but it must not jump into the water.

Given a list of stones’ positions (in units) in sorted ascending order, determine if the frog is able to cross the river by landing on the last stone. Initially, the frog is on the first stone and assume the first jump must be 1 unit.

If the frog’s last jump was k units, then its next jump must be either k - 1, k, or k + 1 units. Note that the frog can only jump in the forward direction.

Note:

The number of stones is ≥ 2 and is < 1,100.
Each stone’s position will be a non-negative integer < 231.
The first stone’s position is always 0.
Example 1:

[0,1,3,5,6,8,12,17]

Return true. The frog can jump to the last stone by jumping
1 unit to the 2nd stone, then 2 units to the 3rd stone, then
2 units to the 4th stone, then 3 units to the 6th stone,
4 units to the 7th stone, and 5 units to the 8th stone.


题解:
首先题目给定的问题规模不超过1000,所以大致上我们需要一个O(n^2)的算法(最坏也应该要达到O(n^2 logn)).
从题目给定的描述来看,大致上是给出了一个状态转移的条件,问最后是否能转化成某一状态。这种题目一般是用搜索或者动态规划。这题我想到的解法是BFS.
我们用两个量来描述一个状态,一个是当前的位置的索引iCur,一个是上一位置的索引iFrt。我们从(0,0)状态开始搜索,所以先将(0,0)入队。之后不断的出队,每次出队就先计算上次的步长k=stones[iCur]-stones[iFrt],查看能否通过跳k-1,k,k+1步达到一个新的石头,如果能够跳到,且这个状态没有入队过,就将该状态入队。如果在某次出队中发现已经达到了终点,则返回true,如果直到队空都没有找到,则说明无法达到,返回false.
现在搜索的过程已经有了,但是我们还需要两个东西:高效地判断一个格子有没有石头,高效地判断一个状态是否已经访问过。首先看判断格子有没有石头,我们可以用一个map做一个反向索引,既对每一个有石头的格子,存储它们在stones中的索引,如果查询到有索引则说明该格子有石头。还有就是判断一个状态是已经访问过。考虑到一个状态是由两个stones的索引构成的,我们可以用一个二维的bool数组来记录。
因为总的状态数有n^2个,所以最后的复杂度也为O(n^2)


代码:

#include <queue>#include <unordered_map>#include <memory.h>typedef pair<int, int> P;class Solution {public:    bool canCross(vector<int>& stones) {        int n = stones.size();        queue<P> que;        unordered_map<int, int> m;        bool vis[n][n];        memset(vis, 0, sizeof(vis));        for (int i = 0; i < stones.size(); i++) {            m[stones[i]] = i;        }        que.push(P(0, 0));        while (!que.empty()) {            P tmp = que.front();            que.pop();            if (tmp.first == n-1) return true;            int k = stones[tmp.first] - stones[tmp.second];            for (int i = k-1; i <= k+1; i++) {                if (i <= 0) continue;                int step = stones[tmp.first] + i;                if (m[step] != 0 && !vis[m[step]][i]) {                    vis[m[step]][i] = true;                    que.push(P(m[step], tmp.first));                }            }        }        return false;    }};
0 0
原创粉丝点击