https://www.acmicpc.net/problem/1987
* 고민했던 부분
- 비트마스킹 발상하기
- N이 30미만 -> 비트마스킹 도전 -> vis를 숫자 1개로 나타내보자.
- 알파벳을 숫자로 표현하기
- A - 'A' =0
- B-A = 1
- C-A = 2
- ...
- A를 1로 (1<<0)
- B를 2로 (1<<1)
- C롤 4로 표한하면 되겠다! (1<<2)
- 1을 알파벳-'A'만큼 밀면 현재 비트가 나온다! // (1<< (A-'A'))
- i번째 비트가 켜진것을 확인하기
- (상태 & 현재비트) !=0 -> i번째 비트는 켜진것. -> already visited
- 주의사항
- 비트연산에는 항상 괄호를 사용할것!
- 모든 탐색이 끝나고 return 될때 정답갱신하는 부분을 어디에 둘지
* 의사코드
알고리즘: 알파벳 보드에서 중복되지 않는 알파벳으로만 이동하는 최장 경로 찾기
입력:
- R: 보드의 행 개수
- C: 보드의 열 개수
- board[R][C]: 각 칸에 알파벳이 적힌 보드
전역변수:
- answer: 찾은 최장 경로의 길이
- dx[], dy[]: 4방향 이동을 위한 방향 배열
함수 DFS(현재_상태, 현재_y좌표, 현재_x좌표, 현재_레벨):
1. 현재 위치의 알파벳을 비트마스크에 추가
- 현재_비트 = 1 << (현재 알파벳 - 'A')
- 현재_상태 = 현재_상태 | 현재_비트
2. 4방향 탐색
각 방향에 대해:
다음_y = 현재_y + dy[i]
다음_x = 현재_x + dx[i]
2.1 경계 체크
만약 다음_y < 0 또는 다음_x < 0 또는
다음_y >= R 또는 다음_x >= C 이면:
다음 방향으로 continue
2.2 다음 위치의 알파벳 비트마스크 계산
다음_비트 = 1 << (다음 알파벳 - 'A')
2.3 방문 여부 체크
만약 (현재_상태 & 다음_비트) != 0 이면:
// 이미 방문한 알파벳이므로
다음 방향으로 continue
2.4 다음 위치로 DFS 호출
DFS(현재_상태, 다음_y, 다음_x, 현재_레벨 + 1)
3. 현재 경로의 탐색이 완료됨
answer = max(answer, 현재_레벨)
return
메인 함수:
1. 입력 받기
- R, C 입력
- board 배열에 알파벳 입력
2. DFS 시작
- DFS(0, 0, 0, 1) 호출
// 초기 상태 = 0, 시작 위치 = (0,0), 초기 레벨 = 1
3. 결과 출력
- answer 출력
* 전체코드
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int r,c,ret;
char a[24][24];
int dy[]={1,0,-1,0};
int dx[]={0,1,0,-1};
void dfs(int state, int y, int x, int level) {
int bit = 1<<(a[y][x]-'A');
state = state | bit;
// cout<<y<<" "<<x<<" "<<state<<"\n";
for(int i=0;i<4;++i) {
int ny=y+dy[i];
int nx=x+dx[i];
if(ny<0 || nx<0 || ny>=r || nx>=c) continue;
int nxt_bit = 1<<(a[ny][nx]-'A');
if((state & nxt_bit) !=0) { // next가 이미 방문했던 곳 인경우
//비트연산자 우선순위 낮음에 주의!!!
//==가 먼저 실행되버리는 문제
continue;
}
dfs(state,ny,nx, level+1);
}
// 현재 경로에서의 탐색이 완료된 시점에 여기로 옴
// (더 갈 곳이 없거나, 가능한 모든 경로를 탐색한 경우)
ret=max(ret,level);
return;
}
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
cin>>r>>c;
for(int i=0;i<r;++i) {
for(int j=0;j<c;++j) {
cin>>a[i][j]; // r,c 아님에 주의!
}
}
dfs(0,0,0,1);
cout<<ret;
return 0;
}
'Algorithm > 비트마스킹' 카테고리의 다른 글
[알고리즘] 백준 2234 성곽 // 비트마스킹, vis의 값에 의미를 부여하라, i번째 비트끄기 (0) | 2025.01.12 |
---|---|
[알고리즘] 백준 1062 가르침 // 조합, 비트마스킹, 백트래킹 (0) | 2025.01.11 |
[알고리즘] 백준 19942 다이어트 // 비트마스킹, 1-idx (0) | 2025.01.11 |
[알고리즘] 백준 17471 게리멘더링 // 비트마스킹, dfs 구역체크는 노드1곳에서 시작 (0) | 2025.01.08 |
[알고리즘] 백준 1285 동전뒤집기 // 비트마스킹, 상태가 2개면 비트마스킹을 생각 (0) | 2025.01.08 |