리뷰
https://www.acmicpc.net/problem/2479
비트 차이가 한개 나는 노드끼리 간선을 연결하고 특정 노드에서 목표 노드로 이동 가능한 경로를 구하는 문제
전역 변수
- N : 배열의 최대 길이를 정의할 상수 변수
- n : 노드의 개수를 저장할 변수
- l : 노드의 비트 개수를 저장할 변수
- H : 노드의 비트 정보를 저장할 배열
- c : 어떤 노드로 부터 왔는지를 저장할 배열
- v : 방문 여부를 체크할 배열
- edges : 간선 정보를 인접 리스트로 저장할 벡터 배열
함수
1. bfs
vector<int> bfs(int sn, int en) {
queue<int> q;
q.push(sn);
v[sn] = true;
while (!q.empty()) {
int cn = q.front(); q.pop();
if (cn == en) break;
for (int nn : edges[cn]) {
if (v[nn]) continue;
v[nn] = true;
c[nn] = cn;
q.push(nn);
}
}
if (!v[en]) return {};
vector<int> path(1, en);
while (en != sn) {
en = c[en];
path.push_back(en);
}
return path;
}
sn에서 en으로 갈 수 있는지를 판단하고, 갈 수 있다면 이동 경로를 반환하기 위한 함수
문제풀이
- n, l값을 입력 받고, n개의 노드의 비트 정보를 H배열에 입력 받아준다.
- 노드간 비트 차이가 정확히 1인 경우에만 인접 리스트 edges에 양방향 간선을 추가해 준다.
- 변수 sn, en에 시작 노드와 목표 노드의 번호를 입력 받아준다. bfs함수에 sn, en을 전달하여 호출한다.
- 정수타입 큐 q를 초기화 하고, sn을 push해주고, v배열을 통해 sn에 방문 처리를 진행해 준다.
- q가 빌때까지 while루프를 수행하고, 매 루프마다 요소를 한개씩 꺼내 변수 cn에 노드 번호를 저장해 준다.
- 기저 조건으로 cn이 en과 같을 경우 목표 노드에 도달한 것이므로 break처리해 준다.
- edges[cn]을 순회하며 다음 노드인 nn이 방문 되어있다면 continue처리해 준다.
- 방문하지 않은 경우 방문처리 및 c[nn] = cn을 통해 cn으로 부터 nn에 도달했음을 명시하고 nn을 q에 삽입해 준다.
- while루프가 종료된 후 v[en]이 false인 경우 en에 도달하지 못한 것이므로 빈 벡터를 반환해 준다.
- v[en]이 true인 경우 정수형 벡터 path를 초기값 en이 들어가 있는 상태로 초기화 해준다.
- en부터 출발하여 c배열을 이용해 en이 sn에 도달할 때 까지 경로를 역추적 하여 path에 push해준다.
- 경로 역추적이 완료하였을 경우 path를 반환해 준다.
- 정수형 벡터 res에 bfs함수의 반환값을 저장하고, res가 비었다면 -1을 출력해 준다.
- res가 비지 않았을 경우 res배열을 뒤집어준 다음 저장된 요소를 공백을 기준으로 출력해 준다.
트러블 슈팅
없음
참고 사항
- N이 최대 1000이므로 브루트포스를 활용해 모든 노드간 비트가 1차이인 해밍 경로만 간선으로 추가해 주었다.
- 경로 역추적 시 en -> sn으로의 경로가 저장되므로 reverse를 통해 경로를 뒤집어 주어야 한다.
정답 코드
#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
const int N = 1001;
int n, l;
string H[N];
int c[N];
bool v[N];
vector<int> edges[N];
vector<int> bfs(int sn, int en) {
queue<int> q;
q.push(sn);
v[sn] = true;
while (!q.empty()) {
int cn = q.front(); q.pop();
if (cn == en) break;
for (int nn : edges[cn]) {
if (v[nn]) continue;
v[nn] = true;
c[nn] = cn;
q.push(nn);
}
}
if (!v[en]) return {};
vector<int> path(1, en);
while (en != sn) {
en = c[en];
path.push_back(en);
}
return path;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n >> l;
for (int i = 1; i <= n; ++i) cin >> H[i];
for (int i = 1; i < n; ++i) {
for (int j = i + 1; j <= n; ++j) {
int cnt = 0;
//cout << H[i].size() << " " << H[j].size() << "\n";
for (int k = 0; k < l; ++k) {
if (H[i][k] != H[j][k]) cnt++;
if (cnt >= 2) break;
}
if (cnt == 1) {
edges[i].push_back(j);
edges[j].push_back(i);
}
}
}
int sn, en; cin >> sn >> en;
vector<int> res = bfs(sn, en);
if (res.empty()) cout << -1;
else {
reverse(res.begin(), res.end());
for (int i : res) cout << i << " ";
}
}
728x90
'알고리즘 공부 > C++' 카테고리의 다른 글
[G2] 백준 16920번 확장 게임 C++ 구현, 너비 우선 탐색, 플러드 필 (0) | 2025.05.29 |
---|---|
[G5] 백준 16938번 캠프 준비 C++ 백트래킹, 정렬 (0) | 2025.05.27 |
[G5] 백준 15661번 링크와 스타트 C++ 백트래킹 (0) | 2025.05.26 |
[G5] 백준 2023번 신기한 소수 C++ 백트래킹, 소수 판정 (0) | 2025.05.26 |
[G4] 백준 25195번 Yes or yes C++ 너비 우선 탐색, 방향 비순환 그래프 (0) | 2025.05.24 |