leetcode之青蛙过河(C++)
參考鏈接
題目描述
一只青蛙想要過河。假定河流被等分為若干個單元格,并且在每一個單元格內都有可能放有一塊石子(也有可能沒有)。青蛙可以跳上石子,但是不可以跳入水中。
給你石子的位置列表stones(用單元格序號升序表示),請判定青蛙能否成功過河(即能否在最后一步跳至最后一塊石子上)。
開始時,青蛙默認已站在第一塊石子上,并可以假定它第一步只能跳躍一個單位(即只能從單元格 1 跳至單元格 2 )。
如果青蛙上一步跳躍了 k 個單位,那么它接下來的跳躍距離只能選擇為 k - 1、k 或 k + 1 個單位。另請注意,青蛙只能向前方(終點的方向)跳躍。
解題思路
我的思路
當成動態規劃問題,“狀態”是當前的石子位置和上一步的距離,“選擇”是跳到之后的哪一塊石子。當前“狀態”能否到達終點,取決于下一步后能否到達終點。
我們每到一個位置,就向后搜索下一步石子,如果下一步石子距離當前位置距離不大于上一步距離加1且不小于距離減1,說明可以跳過去,而且后面還可能有合適的石子,接著向后搜索;如果下一步石子距離當前位置大于了上一步距離加1,就不必向后搜索了,因為后面的距離更遠。所以每到一個位置,下一步石子可能有幾種情況,我們只需要其中一種可以到達終點就可以了,即對它們的結果取或。
官方思路
同樣是動態規劃,不過技巧比較多。它的狀態表的含義是,dp[i][k] 表示青蛙能否達到「現在所處的石子編號」為 i 且「上一次跳躍距離」為 k 的狀態。狀態轉移方程為:
dp[i][k]=dp[j][k?1]∪dp[j][k]∪dp[j][k+1]dp\left [ i\right ]\left [ k\right ]=dp\left [ j\right ]\left [ k-1\right ]\cup dp\left [ j\right ]\left [ k\right ]\cup dp\left [ j\right ]\left [ k+1\right ]dp[i][k]=dp[j][k?1]∪dp[j][k]∪dp[j][k+1]
優化技巧有:
代碼
我的思路
class Solution { public:unordered_map<string, bool> mp;bool dp(vector<int>& stones, int start, int prev){if (start == stones.size() - 1){return true;}if (mp.count(to_string(start) + '_' + to_string(prev)) == 1){return mp[to_string(start) + '_' + to_string(prev)];}bool flag = false;for (int i = start + 1; i < stones.size(); i++){if ((stones[i] - stones[start]) > prev + 1){break;}if (i == stones.size() - 1 && (stones[i] - stones[start]) < prev - 1){break;}if ((stones[i] - stones[start]) >= prev - 1){flag = flag || dp(stones, i, stones[i] - stones[start]);}}mp[to_string(start) + '_' + to_string(prev)] = flag;return flag;}bool canCross(vector<int>& stones) {return dp(stones, 0, 0);} };官方思路
class Solution { public:bool canCross(vector<int>& stones) {int n = stones.size();vector<vector<int>> dp(n, vector<int>(n));dp[0][0] = true;for (int i = 1; i < n; ++i) {if (stones[i] - stones[i - 1] > i) {return false;}}for (int i = 1; i < n; ++i) {for (int j = i - 1; j >= 0; --j) {int k = stones[i] - stones[j];if (k > j + 1) {break;}dp[i][k] = dp[j][k - 1] || dp[j][k] || dp[j][k + 1];if (i == n - 1 && dp[i][k]) {return true;}}}return false;} };總結
以上是生活随笔為你收集整理的leetcode之青蛙过河(C++)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用PartitionMagic分区失败
- 下一篇: Mindjet MindManager