제민

17244 아맞다우산 (비트마스킹) 본문

코테연습일지/그래프 이론

17244 아맞다우산 (비트마스킹)

jemin0619 2024. 2. 12. 21:52

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

 

17244번: 아맞다우산

경재씨는 저녁 약속을 가기 전 챙기지 않은 물건들이 있는 지 확인하고 있다. 필요한 물건은 전부 챙긴 것 같았고 외출 후 돌아오는 길에 경재씨는 외쳤다. "아 맞다 우산!!!" 경재 씨는 매번 외출

www.acmicpc.net

챙겨야 하는 물건의 수가 최대 5개로 작으므로 비트마스크를 사용해 해결할 수 있다.

 

#include <bits/stdc++.h>
using namespace std;
int N,M,Bit,idx;
bool vis[53][53][35]; //y x bit
char board[53][53];
int dy[4]={1,0,-1,0};
int dx[4]={0,1,0,-1};
queue<tuple<int,int,int,int>> Q; //y x cnt bit

int main(void){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin>>N>>M; //가로 세로 
	for(int i=0;i<M;i++){
		for(int j=0;j<N;j++){
			cin>>board[i][j];
			if(board[i][j]=='S'){Q.push(make_tuple(i,j,0,0)); vis[i][j][0]=true;}
			if(board[i][j]=='X'){board[i][j]=(idx++)+'0';}
		}
	}
	Bit=(1<<idx)-1;
	//idx는 X의 갯수임
	//X가 4개라면 Bit==15
	//이를 2진수로 바꾸면 1111이므로 한 자리당 X 한 개를 의미한다.
	
	while(!Q.empty()){
		auto cur=Q.front(); Q.pop();
		int curY,curX,curCnt,curBit;
		tie(curY,curX,curCnt,curBit)=cur;
		
		if(board[curY][curX]=='E'&&curBit==Bit){
			cout<<curCnt<<'\n';
			break;
		}
		
		for(int dir=0;dir<4;dir++){
			int ny=curY+dy[dir];
			int nx=curX+dx[dir];
			int nb=curBit;
			if(ny<0||nx<0||ny>=M||nx>=N) continue;
			if(board[ny][nx]=='#') continue;
			
			if(board[ny][nx]>='0' && board[ny][nx]<='4'){nb|=(1<<(board[ny][nx]-'0'));}
			if(vis[ny][nx][nb]) continue;
			vis[ny][nx][nb]=true; Q.push(make_tuple(ny,nx,curCnt+1,nb));
		}
	} 
	return 0;
}

비트마스크를 사용해 문제를 푼 건 이게 처음인데 굉장히 신박한 방식이라고 느꼈다.

'코테연습일지 > 그래프 이론' 카테고리의 다른 글

5558 チーズ (Cheese)  (0) 2024.03.02
14923 미로 탈출  (0) 2024.03.02
16234 인구 이동  (0) 2024.02.11
16985 Maaaaaaaaaze  (2) 2024.02.08
17141 연구소 2  (0) 2024.02.07