[Gold II]
https://www.acmicpc.net/problem/3109
풀이
우선, 찬찬히 살펴보면,
첫 번째 열의 모든 칸에서부터, 최대한 많이 마지막 열의 칸으로 연결해야 한다.
이 때, Greedy하게 첫째 열의 맨 위(첫 번째) 칸에서부터 시작해도 되며,
오른쪽 위 / 오른쪽 / 오른쪽 아래 3개의 선택지 중, 오른쪽 위를 선택하는 것이 이후 파이프 연결에서 가장 유리하므로, 또한 Greedy하게 오른쪽 위 - 오른쪽 - 오른쪽 아래 순으로, 가능한 선택지를 바로 고르는 것이 좋다.
따라서 수도 코드로 간단하게 표현하자면 아래와 같이 진행하게 되는 것이다.
for 모든 첫째 열의 칸들에 대해:
while 마지막 열에 갈 때까지:
if 오른쪽 위가 비어있다면:
오른쪽 위를 선택
elif 오른쪽이 비어있다면:
오른쪽을 선택
elif 오른쪽 아래가 비어있다면:
오른쪽 아래를 선택
else:
이 루트 폐기
첫 시도는 TLE.
#include <algorithm>
#include <iostream>
#include <set>
#include <string>
#include <vector>
#define init cin.tie(0)->ios_base::sync_with_stdio(0);
using namespace std;
bool M[10001][501] = {};
bool dfs(int i, int j, int R, int C) {
// 칸을 넘어가면 false, 마지막 열일 시 true. (기저조건)
if (i < 0 || i >= R || j < 0 || j >= C) return false;
if (!M[i][j]) return false;
if (j == C - 1) return true;
// 우측 위, 우측, 우측 아래 순으로 dfs 호출.
if (dfs(i - 1, j + 1, R, C))
M[i][j] = false;
else if (dfs(i, j + 1, R, C))
M[i][j] = false;
else if (dfs(i + 1, j + 1, R, C))
M[i][j] = false;
else
return false;
return true;
}
int main() {
init;
int R, C;
cin >> R >> C;
char ch;
int result = 0;
// 입력
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
cin >> ch;
if (ch == '.') M[i][j] = true;
}
}
for (int i = 0; i < R; i++) {
if (dfs(i, 0, R, C)) result++;
}
cout << result;
}
풀이 2
시간 초과가 나 생각해 보니, 아래 부분에서, "마지막 열 도달에 성공했을 때" 만 방문 체크를 해 주었는데,
만약 마지막 열 도달에 실패했을 때에도, 그 칸에서 뻗어나가는 것은 항상 마지막 열에 도달하지 못한다는 것을 뜻한다.
그러므로, 마지막 열 도달에 실패해도, 방문 체크를 한다면 지수적으로 Time Complexity가 증가하지 않으므로 풀릴 것이라 생각했다.
// 우측 위, 우측, 우측 아래 순으로 dfs 호출.
if (dfs(i - 1, j + 1, R, C))
M[i][j] = false;
else if (dfs(i, j + 1, R, C))
M[i][j] = false;
else if (dfs(i + 1, j + 1, R, C))
M[i][j] = false;
else
return false;
굉장히 빠르게 AC!
실력이 좀 늘었나...? 히히
#include <algorithm>
#include <iostream>
#include <set>
#include <string>
#include <vector>
#define init cin.tie(0)->ios_base::sync_with_stdio(0);
using namespace std;
bool M[10001][501] = {};
bool dfs(int i, int j, int R, int C) {
// 칸을 넘어가면 false, 마지막 열일 시 true. (기저조건)
if (i < 0 || i >= R || j < 0 || j >= C) return false;
if (!M[i][j]) return false;
if (j == C - 1) return true;
// 우측 위, 우측, 우측 아래 순으로 dfs 호출.
if (dfs(i - 1, j + 1, R, C)) {
M[i][j] = false;
return true;
}
if (dfs(i, j + 1, R, C)) {
M[i][j] = false;
return true;
}
if (dfs(i + 1, j + 1, R, C)) {
M[i][j] = false;
return true;
}
M[i][j] = false;
return false;
}
int main() {
init;
int R, C;
cin >> R >> C;
char ch;
int result = 0;
// 입력
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
cin >> ch;
if (ch == '.') M[i][j] = true;
}
}
for (int i = 0; i < R; i++) {
if (dfs(i, 0, R, C)) result++;
}
cout << result;
}