leetcode之青蛙过河(C++)
參考鏈接
題目描述
一只青蛙想要過(guò)河。假定河流被等分為若干個(gè)單元格,并且在每一個(gè)單元格內(nèi)都有可能放有一塊石子(也有可能沒(méi)有)。青蛙可以跳上石子,但是不可以跳入水中。
給你石子的位置列表stones(用單元格序號(hào)升序表示),請(qǐng)判定青蛙能否成功過(guò)河(即能否在最后一步跳至最后一塊石子上)。
開(kāi)始時(shí),青蛙默認(rèn)已站在第一塊石子上,并可以假定它第一步只能跳躍一個(gè)單位(即只能從單元格 1 跳至單元格 2 )。
如果青蛙上一步跳躍了 k 個(gè)單位,那么它接下來(lái)的跳躍距離只能選擇為 k - 1、k 或 k + 1 個(gè)單位。另請(qǐng)注意,青蛙只能向前方(終點(diǎn)的方向)跳躍。
解題思路
我的思路
當(dāng)成動(dòng)態(tài)規(guī)劃問(wèn)題,“狀態(tài)”是當(dāng)前的石子位置和上一步的距離,“選擇”是跳到之后的哪一塊石子。當(dāng)前“狀態(tài)”能否到達(dá)終點(diǎn),取決于下一步后能否到達(dá)終點(diǎn)。
我們每到一個(gè)位置,就向后搜索下一步石子,如果下一步石子距離當(dāng)前位置距離不大于上一步距離加1且不小于距離減1,說(shuō)明可以跳過(guò)去,而且后面還可能有合適的石子,接著向后搜索;如果下一步石子距離當(dāng)前位置大于了上一步距離加1,就不必向后搜索了,因?yàn)楹竺娴木嚯x更遠(yuǎn)。所以每到一個(gè)位置,下一步石子可能有幾種情況,我們只需要其中一種可以到達(dá)終點(diǎn)就可以了,即對(duì)它們的結(jié)果取或。
官方思路
同樣是動(dòng)態(tài)規(guī)劃,不過(guò)技巧比較多。它的狀態(tài)表的含義是,dp[i][k] 表示青蛙能否達(dá)到「現(xiàn)在所處的石子編號(hào)」為 i 且「上一次跳躍距離」為 k 的狀態(tài)。狀態(tài)轉(zhuǎn)移方程為:
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]
優(yōu)化技巧有:
代碼
我的思路
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;} };總結(jié)
以上是生活随笔為你收集整理的leetcode之青蛙过河(C++)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 使用PartitionMagic分区失败
- 下一篇: 字符串压缩之C++实现