강을 건너는 개구리가 있다고 가정해 봅시다. 강은 x 단위로 나뉘며 각 단위에는 돌이 있을 수 있습니다. 개구리는 돌 위에서는 뛸 수 있지만 물에서는 뛸 수 없습니다. 여기에 오름차순으로 정렬된 돌의 위치 목록이 있습니다. 개구리가 마지막 돌에 착지하여 강을 건널 수 있는지 여부를 확인해야 합니다. 처음에 개구리는 첫 번째 돌 위에 있고 첫 번째 점프는 1 유닛이어야 한다고 가정합니다.
개구리의 현재 점프가 k 단위였을 때 다음 점프는 k - 1, k 또는 k + 1 단위여야 합니다. 그리고 개구리는 앞으로만 점프할 수 있습니다.
따라서 주어진 배열이 [0,1,3,4,5,7,9,10,12]와 같으면 개구리는 1단위에서 두 번째 돌로, 2단위는 다음과 같이 참이 됩니다. 3번째 스톤, 그리고 다시 2 유닛은 4번째 스톤, 3 유닛은 6번째 스톤, 4 유닛은 7번째 스톤, 마지막으로 5 유닛은 8번째 스톤으로.
이 문제를 해결하기 위해 다음 단계를 따릅니다. −
- 방문이라는 지도 정의
- canCross() 함수를 정의하면 배열 스톤이 사용되며 pos는 0으로 초기화, k는 0으로 초기화,
- 키 :=pos OR(왼쪽 시프트 k 11비트)
- 방문한 키에 키가 있으면 -
- 방문 반품[키]
- 초기화 i의 경우:=pos + 1, i <돌의 크기일 때 업데이트(i를 1만큼 증가), 수행 -
- 갭 :=돌[i] - 돌[pos]
- 갭
- 다음 부분은 무시하고 다음 반복으로 건너뜁니다.
- 갭> k + 1이면 −
- 방문함[key] :=false
- 거짓 반환
- canCross(stones, i, gap) 함수 호출이 0이 아닌 경우 -
- 방문함[키] =사실
- 참을 반환
이해를 돕기 위해 다음 구현을 살펴보겠습니다. −
예시
#include <bits/stdc++.h> using namespace std; typedef long long int lli; class Solution { public: unordered_map < lli, int > visited; bool canCross(vector<int>& stones, int pos = 0, int k = 0) { lli key = pos | k << 11; if(visited.find(key) != visited.end())return visited[key]; for(int i = pos + 1; i < stones.size(); i++){ int gap = stones[i] - stones[pos]; if(gap < k - 1)continue; if(gap > k + 1){ return visited[key] = false; } if(canCross(stones, i, gap))return visited[key] = true; } return visited[key] = (pos == stones.size() - 1); } }; main(){ Solution ob; vector<int> v = {0,1,3,5,6,8,12,17}; cout << (ob.canCross(v)); }
입력
0,1,3,5,6,8,12,17
출력
1