알고리즘/백준

BOJ 3109 빵집 / C++

내이름은 킹햄찌 2022. 9. 15. 21:25

https://www.acmicpc.net/problem/3109

 

3109번: 빵집

유명한 제빵사 김원웅은 빵집을 운영하고 있다. 원웅이의 빵집은 글로벌 재정 위기를 피해가지 못했고, 결국 심각한 재정 위기에 빠졌다. 원웅이는 지출을 줄이고자 여기저기 지출을 살펴보던

www.acmicpc.net

아이디어

이 문제는 사실 만족할만큼 이해하지는 못한 것 같습니다.

이 문제의 풀이인 DFS를 통해 간선 카운팅을 하는방식은 가장 처음에 생각했는데 위에서 언급한 부분 때문에 바로 풀이해내지는 못했습니다. 그 외에 BFS를 통해 간선의 한 부분에서 갈 수 있는 최댓값을 구하는 문제인가 등등 접근을 많이 해봤지만 반례가 너무나 쉽게 떠올라 다른분들의 풀이를 보고야 말았죠.

왼쪽에서 오른쪽으로 DFS를 이용하여 도착할때 마다 카운팅을 하는 방식으로 풀이를 할 수 있는데요. 여기서 가장 중요한것은 y축 탐색시 대각선 하단을 가장 먼저 탐색을 해야한다는 것이다. 아래에 주석을 달아놓은것 처럼 아래를 방문할때 더 큰 파이프라인 갯수가 나올 경우를 빠뜨릴 수 있기 때문이라는 것은 알았는데 왜? 가 해결이 안된 상태입니다.

단순히 반례를 보면서 손으로 따라가보는 것 말고는 검증할 방법이 없었는데 혹여 추후에 이해가 된다면 자세한 풀이 남기겠습니다. 또는 아시는분은 지식 공유 부탁드립니다.

 

#include <iostream>
#include <string>
#include <vector>
using namespace std;

int r, c;
int cnt;
// y의 대각선 축으로 먼저 탐색하게 하는게 포인트
//위를 먼저 방문할 경우에 아래를 먼저 방문할때 더 큰 파이프라인 갯수가 나올경우를 빠뜨림
int my[3] = { -1,0,1 };
int mx[3] = { 1,1,1 };
vector<vector<char>> graph;

void input() {
	cin >> r >> c;
	graph.resize(r, vector<char>(c));
	for (int i = 0; i < r; i++) {
		for (int j = 0; j < c; j++) {
			cin >> graph[i][j];
		}
	}
}

bool dfs(int y, int x) {
	if (x == c - 1) {
		cnt++;
		return true;
	}

	graph[y][x] = 'x';
	for (int i = 0; i < 3; i++) {
		int ny = y + my[i];
		int nx = x + mx[i];
		if (ny >= r || ny<0 || nx>=c || nx < 0 ) continue;
		if (graph[ny][nx] == 'x') continue;
		//탐색을 더 이어갈지 체크
		if (dfs(ny,nx))
			return true;
	}
	return false;

}
void solution() {
	for (int i = 0; i < r; i++) {
		dfs(i, 0);
	}
	cout << cnt;
}

int main(void) {
	input();
	solution();
}