당신은 주제를 찾고 있습니까 “아 맞다 우산 – [천관사복] 진옥으로 비교당하는 아이“? 다음 카테고리의 웹사이트 https://you.charoenmotorcycles.com 에서 귀하의 모든 질문에 답변해 드립니다: https://you.charoenmotorcycles.com/blog. 바로 아래에서 답을 찾을 수 있습니다. 작성자 아 맞다 우산 이(가) 작성한 기사에는 조회수 9,742회 및 좋아요 872개 개의 좋아요가 있습니다.
아 맞다 우산 주제에 대한 동영상 보기
여기에서 이 주제에 대한 비디오를 시청하십시오. 주의 깊게 살펴보고 읽고 있는 내용에 대한 피드백을 제공하세요!
d여기에서 [천관사복] 진옥으로 비교당하는 아이 – 아 맞다 우산 주제에 대한 세부정보를 참조하세요
■원곡 – https://youtu.be/olWvy0PiLfA
■짤막한 영상제작후기 – https://blog.naver.com/sookk6577/222572372804
===================================
\”인간들은 엉터리 날조를 사랑해 마지않는다.\” -천관사복 90장
…엉터리 날조 죄송합니다
아 맞다 우산 주제에 대한 자세한 내용은 여기를 참조하세요.
17244번: 아맞다우산
아 맞다 우산!!!” 경재 씨는 매번 외출하고 나서야 어떤 물건을 집에 놓고 왔다는 것을 떠올릴 때마다 자책감에 시달리는 것이 너무 싫었다. 외출이 잦은 경재 씨는 …
Source: www.acmicpc.net
Date Published: 8/17/2022
View: 8106
[ 백준 17244 ] 아 맞다 우산 (C++)
[ 백준 17244 ] 아 맞다 우산 (C++) · 1) 시작점에서 주어진 물건을 모두 줍고 도착점까지 갈 때 걸리는 최소 시간을 찾아야 하는 문제이다. · 본인은 이 …Source: yabmoons.tistory.com
Date Published: 2/26/2021
View: 8801
아 맞다 우산
아 맞다 우산. 아 맞다 우산. 999 subscribers. Subscribe. 우산 블로그☂ / Blog. Home. Veos. Playlists. Community. Channels.
Source: www.youtube.com
Date Published: 4/5/2021
View: 1048
백준 17244번 아맞다우산 – 꾸준함
문제 링크입니다: https://www.acmicpc.net/problem/17244 17244번: 아맞다우산 경재씨는 저녁 약속을 가기 전 챙기지 않은 물건들이 있는 지 확인 …
Source: jaimemin.tistory.com
Date Published: 2/26/2022
View: 4403
[백준][C++] 17244 아맞다우산 – 거창한 시작
알고리즘 종류. – 구현. – BFS. 사고 과정. – 이 문제에서 중요한 조건은 재방문 처리이다. 특히 아래와 같은 상황이다. 시작점 S에서 빨간색 선으로 …
Source: conkjh032.tistory.com
Date Published: 4/1/2021
View: 9736
옥짱 – 아 맞다 우산
Stream 옥짱 – 아 맞다 우산 by 옥짱곡가 on desktop and mobile. Play over 265 million tracks for free on SoundCloud.
Source: soundcloud.com
Date Published: 2/16/2021
View: 3544
[백준] 17244번 : 아맞다우산 – 개발하는 고라니
[BFS + 비트마스크]. N x M 격자 맵에서 ‘X’로 표시된 모든 물건을 챙기고 탈출구 ‘E’로 최소한의 움직임으로 나가는 방법을 찾는 문제.Source: dev-gorany.tistory.com
Date Published: 3/27/2021
View: 3692
[백준 17244] 아맞다우산 (Java) – 어흥
[백준 17244] 아맞다우산 (Java) ; Main ; Info ; public Info(int y, int x, int val, int knum) ; static vo bfs() ; public static …Source: imnotabear.tistory.com
Date Published: 4/23/2022
View: 2906
boj 17244 아맞다우산 – 취미가 알고리즘
boj 17244 아맞다우산 … 챙겨야 하는 물건은 최대 5개이므로 bfs + 비트마스킹이 가능합니다. visit[x][y][bit]: 좌표 (x, y)에 도착했을 때 찾은 물건의 …
Source: emoney96.tistory.com
Date Published: 12/14/2022
View: 5682
주제와 관련된 이미지 아 맞다 우산
주제와 관련된 더 많은 사진을 참조하십시오 [천관사복] 진옥으로 비교당하는 아이. 댓글에서 더 많은 관련 이미지를 보거나 필요한 경우 더 많은 관련 기사를 볼 수 있습니다.
주제에 대한 기사 평가 아 맞다 우산
- Author: 아 맞다 우산
- Views: 조회수 9,742회
- Likes: 좋아요 872개
- Date Published: 2021. 11. 18.
- Video Url link: https://www.youtube.com/watch?v=qx6OegXS1Y0
17244번: 아맞다우산
문제
경재씨는 저녁 약속을 가기 전 챙기지 않은 물건들이 있는 지 확인하고 있다. 필요한 물건은 전부 챙긴 것 같았고 외출 후 돌아오는 길에 경재씨는 외쳤다.
“아 맞다 우산!!!”
경재 씨는 매번 외출하고 나서야 어떤 물건을 집에 놓고 왔다는 것을 떠올릴 때마다 자책감에 시달리는 것이 너무 싫었다.
외출이 잦은 경재 씨는 반복되는 일을 근절하기 위해 꼭 챙겨야 할 물건들을 정리해보았다. 하지만 지갑, 스마트폰, 우산, 차 키, 이어폰, 시계, 보조 배터리 등 종류와 개수가 너무 많았다.
평소 불필요한 움직임을 아주 싫어하는 경재 씨는 이 물건들을 최대한 빠르게 챙겨서 외출하는 이동 경로를 알고 싶었다.
경재 씨는 한 걸음에 상하좌우에 인접한 칸으로만 움직일 수 있다.
경재 씨를 위해 집을 위에서 바라본 모습과 챙겨야 할 물건들의 위치들을 알고 있을 때, 물건을 모두 챙겨서 외출하기까지 최소 몇 걸음이 필요한지 구하는 프로그램을 작성하자.
[ 백준 17244 ] 아 맞다 우산 (C++)
백준의 아 맞다 우산(17244) 문제이다.
[ 문제 바로가기 ] [ 문제풀이 ]1) 시작점에서 주어진 물건을 모두 줍고 도착점까지 갈 때 걸리는 최소 시간을 찾아야 하는 문제이다.
본인은 이 문제를 너비우선탐색(BFS)을 이용해서 풀어보았는데, 방문체크를 단순히 ‘몇 개 주웠는지’ 로는
풀 수가 없다. 왜냐하면 다음과 같은 경우를 생각해보자.
위와 같은 맵이 존재할 때, 우리가 주워야할 물건은 4개가 있다. 그런데 단순히 몇 개 주었는지만으로 체크를 한다면
다음과 같은 경우가 발생할 것이다.
시작점 → 빨강색X로 향할 때 체크 : 0개를 주웠을 때 빨강색 X에 방문한 적이 있는지 ? → 없으므로 1개를 주웠다고
표시하며 방문 → 파랑색 X로 향할 때 체크 : 1개를 주웠을 때 파랑색 X에 방문한 적이 있는지 ? → 없으므로 파랑색 물건을
줍고 2개를 주웠다고 표시하며 방문 → 빨강색X로 향할 때 체크 : 2개를 주웠을 때 빨강색 X에 방문한 적이 있는지 ?
→ 없으므로 3개를 주웠다고 표시하며 방문 → 파랑색 X로 향할 때 체크 : 4개를 주웠을 때 파랑색 X에 방문한 적이
있는지 ? → 없으므로 파랑색 물건을 줍고 4개를 주웠다고 표시하며 방문 → E로 향함.
이렇게 되면 실제로 물건을 4개다 줍지 않았음에도, 4개를 주웠다고 잘못 판단하고 결론에 도달하는 경우가 존재한다.
따라서 단순히 ‘몇 개를 주었는지’ 로는 문제를 해결할 수가 없다.
접근할 때, ‘몇 개’가 아닌 ‘빨강색 X를 주웠는지’ 혹은 ‘파랑색 X를 주웠는지’ 이런 식의 개념으로 접근을 해야 한다.
그래서 이 부분을 위해서 본인은 비트마스크를 사용했다.
본인은 물건들을 X로 놓지 않고, 각 물건들이 입력됨과 동시에 번호로 표시해 주었다.
예를 들면 위의 경우, 빨강색 X = ‘0’ , 파랑색 X = ‘1’, 나머지 X들 = ‘2’, ‘3’ 이런식으로 char형 문자로 저장해 주었다.
그리고 위의 물건들을 비트마스크로 표시하는 것이다. 주웠을 때는 1, 아직 줍지 않았을 때는 0
최종적으로 우리가 모든 물건을 다 주웠다면 모든 비트가 ‘1’로 표시되어 있을 것이다.
위의 그림같은 경우 주워야할 물건이 4개이므로 ‘1111’ 이 되어야 모두 주운 것이다.
여기서 잘 생각해야 할 것이, 실제로 우리는 2진수로 비트를 표현하는 것이 아니라 ,10진수를 2진수 처럼 표현할 것이다.
2) 본인은 방문체크를 위한 bool 형 Visit배열을 3차원으로 선언해 주었다.
크기는 Visit[50][50][35]로 선언해 주었다.
앞에 50 50은 맵의 최대 크기, 즉 x좌표와 y좌표를 나타내는 부분이고, 뒤에 35를 한번 봐보자.
물건은 최대 5개까지 있을 수 있다. 즉, 물건 5개를 모두 주웠다면 비트가 ‘11111’ 로 표현되야 할 것이다.
하지만, 우리는 실제로 2진수를 사용하는 것이 아닌 10진수를 2진수처럼 표현하는 것이다. 즉, ‘11111’을 십진수로
나타내면 31이다. 즉, 물건이 최대 5개가 있더라도 ‘11111’보다 더 큰 수는 나오지 않기 때문에, 다시 말해서 ’31’보다
더 큰 수는 나오지 않기 때문에 배열의 크기를 31보다 조금 더 큰 35로 설정해 주었다.
그럼 물건을 줍게되면 어떻게 체크를 해줘야 할까 ??
예를 들어서 물건이 4개가 있고, 현재 비트가 0000 이라고 가정해보자. 즉, 아직 물건을 하나도 줍지 못한 상태이다.
여기서 ‘0’번 물건을 주웠다고 가정해보면, 아마 비트는 0001이 될 것이다.
0000 과 어떤 값을 무슨 연산을 해줘야 0001이 나올까 ?? 바로 0001과 or 연산을 하면 된다.
0000 | 0001 = 0001 이기 때문이다.
그럼 ‘1’번물건을 주웠다고 가정해보자. 아마 비트는 0010이 되어야 할 것이다.
이 값은, 0000 | 0010 을 해주면 나오게 되는 값이다.
즉 ! “1을 물건의 번호만큼 << shift 연산 후, or연산을 진행" 하면 되는 것이다. '0'번 물건을 주운 경우를 보자. 현재 비트 = 0000 이고, 위에서 말한대로 1을 물건의 번호만큼 << shift연산 후 or 연산을 해보자. 1을 물건의 번호인 '0'만큼 shift연산을 하게되면, 0001이 될 것이다. 1은 2진수로 0001이기 때문에 ! 그 후, 0000과 0001을 or 연산을 하면 '0'번 물건을 주웠습니다 라고 표시할 수 있는 비트가 생성되는 것이다. '1'번 물건을 줍게 되면, 1을 '1'번만큼 << shift연산을 하게되면 0001 → 0010 이 되고, 이 후 or 연산을 하게 되면 0010 이 되는 것이다. 이런식으로 x번 물건을 주웠는지 안주웠는지를 체크를 해주면서 탐색을 진행하면 된다. 3) 위에서는 비트마스크를 이용한 풀이를 알아보았다. 본인은 또 한가지 방법으로 풀이를 해보았는데, 이 방법은 모든 물건에 순서를 만들어 주는 것이다. 물건을 주울 순서를 정한 후, 해당 물건을 순서대로 주워보고 걸리는 시간 중 최소값을 찾는 방식이다. 따라서 이 풀이에는 '순열'을 구현하는 과정이 들어간다. 순열을 구현하는 방법을 모른다면 아래의 글을 읽고 오자 ! [ 순열 구현하기 (Click) ] 각 물건들의 순서를 정해주고, BFS 탐색으로 시작점 → 순서가 정해진 물건들을 순서대로 줍기 → 도착점 으로 가는 시간들 중, 최소 시간을 정답으로 채택하는 방식이다. 주의해야 할 부분은 주워야 할 물건의 갯수가 0개일 때가 존재한다. 따라서, 0 개일 때는, 시작점에서 도착점으로 바로 탐색을 해줘야 하는 것이다. [ 비트마스크 풀이 소스코드 ] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 #include < iostream > #include < queue > #define endl ”
” #define MAX 50 using namespace std ; int N, M, Bit; char MAP[MAX][MAX]; bool Visit[MAX][MAX][ 35 ]; int dx[] = { 0 , 0 , 1 , – 1 }; int dy[] = { 1 , – 1 , 0 , 0 }; pair < int , int > Start, End; void Input() { int Idx = 0 ; cin > > M > > N; for ( int i = 0 ; i < N; i + + ) { for ( int j = 0 ; j < M; j + + ) { cin > > MAP[i][j]; if (MAP[i][j] = = ‘S’ ) { Start.first = i; Start.second = j; } else if (MAP[i][j] = = ‘X’ ) { MAP[i][j] = (Idx + + ) + ‘0’ ; } } } Bit = ( 1 < < Idx) - 1 ; } void Solution() { queue < pair < pair < int , int > , pair < int , int > > > Q; Q.push( make_pair ( make_pair (Start.first, Start.second), make_pair ( 0 , 0 ))); Visit[Start.first][Start.second][ 0 ] = true ; while (Q.empty() = = 0 ) { int x = Q. front ().first.first; int y = Q. front ().first.second; int Cnt = Q. front ().second.first; int Bit_State = Q. front ().second.second; Q. pop (); if (MAP[x][y] = = ‘E’ & & Bit_State = = Bit) { cout < < Cnt < < endl ; return ; } for ( int i = 0 ; i < 4 ; i + + ) { int nx = x + dx[i]; int ny = y + dy[i]; int nB = Bit_State; if (nx > = 0 & & ny > = 0 & & nx < N & & ny < M) { if ( '0' < = MAP[nx][ny] & & MAP[nx][ny] < '5' ) { nB = Bit_State | ( 1 < < MAP[nx][ny] - '0' ); if (Visit[nx][ny][nB] = = false ) { Visit[nx][ny][nB] = true ; Q.push( make_pair ( make_pair (nx, ny), make_pair (Cnt + 1 , nB))); } } else if (MAP[nx][ny] ! = '#' ) { if (Visit[nx][ny][nB] = = false ) { Visit[nx][ny][nB] = true ; Q.push( make_pair ( make_pair (nx, ny), make_pair (Cnt + 1 , nB))); } } } } } } void Solve() { Input(); Solution(); } int main( void ) { ios::sync_with_stdio( false ); cin .tie( NULL ); cout .tie( NULL ); //freopen("Input.txt", "r", stdin); Solve(); return 0 ; } Colored by Color Scripter cs [ 순열을 통한 풀이 소스코드 ] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 #include < iostream > #include < queue > #include < vector > #include < cstring > #define endl ”
” #define MAX 50 using namespace std ; int N, M, Answer = 987654321 ; char MAP[MAX][MAX]; bool Visit[MAX][MAX]; bool Select[ 5 ]; int dx[] = { 0 , 0 , 1 , – 1 }; int dy[] = { 1 , – 1 , 0 , 0 }; vector < pair < int , int > > V, Order; pair < int , int > Start, End; int Min( int A, int B) { if (A < B) return A; return B; } void Input() { cin > > M > > N; for ( int i = 0 ; i < N; i + + ) { for ( int j = 0 ; j < M; j + + ) { cin > > MAP[i][j]; if (MAP[i][j] = = ‘X’ ) { V. push_back ( make_pair (i, j)); MAP[i][j] = ‘.’ ; } else if (MAP[i][j] = = ‘S’ ) { Start.first = i; Start.second = j; MAP[i][j] = ‘.’ ; } else if (MAP[i][j] = = ‘E’ ) { End.first = i; End.second = j; MAP[i][j] = ‘.’ ; } } } } int BFS( int Sx, int Sy, int Ex, int Ey) { memset(Visit, false , sizeof (Visit)); queue < pair < pair < int , int > , int > > Q; Q.push( make_pair ( make_pair (Sx, Sy), 0 )); Visit[Sx][Sy] = true ; while (Q.empty() = = 0 ) { int x = Q. front ().first.first; int y = Q. front ().first.second; int Cnt = Q. front ().second; Q. pop (); if (x = = Ex & & y = = Ey) return Cnt; for ( int i = 0 ; i < 4 ; i + + ) { int nx = x + dx[i]; int ny = y + dy[i]; if (nx > = 0 & & ny > = 0 & & nx < N & & ny < M) { if (MAP[nx][ny] = = '.' & & Visit[nx][ny] = = false ) { Visit[nx][ny] = true ; Q.push( make_pair ( make_pair (nx, ny), Cnt + 1 )); } } } } } void Calculate() { int S = Order. size (); int Dist = BFS(Start.first, Start.second, Order[ 0 ].first, Order[ 0 ].second); for ( int i = 0 ; i < S - 1 ; i + + ) { Dist = Dist + BFS(Order[i].first, Order[i].second, Order[i + 1 ].first, Order[i + 1 ].second); } Dist = Dist + BFS(Order[S - 1 ].first, Order[S - 1 ].second, End.first, End.second); Answer = Min(Answer, Dist); } void DFS( int Cnt) { if (Cnt = = V. size ()) { Calculate(); return ; } for ( int i = 0 ; i < V. size (); i + + ) { if (Select[i] = = true ) continue ; Select[i] = true ; Order. push_back (V[i]); DFS(Cnt + 1 ); Order.pop_back(); Select[i] = false ; } } void Solution() { if (V. size () = = 0 ) { Answer = BFS(Start.first, Start.second, End.first, End.second); cout < < Answer < < endl ; return ; } DFS( 0 ); cout < < Answer < < endl ; } void Solve() { Input(); Solution(); } int main( void ) { ios::sync_with_stdio( false ); cin .tie( NULL ); cout .tie( NULL ); //freopen("Input.txt", "r", stdin); Solve(); return 0 ; } Colored by Color Scripter cs
백준 17244번 아맞다우산
문제 링크입니다: https://www.acmicpc.net/problem/17244
비트마스킹을 통해 아이템을 주웠는지 판별해야하는 흥미로운 BFS 문제였습니다.
물건 ‘X’ 마다 각각 고유 인덱스를 부여하여 비트 연산을 통해 주웠는지를 판별하는 것이 핵심이였습니다.
물건은 최대 5개이기 때문에 인덱스는 최대 4이고 0 ~ 4 까지 모두 표시하기 위해서는 크기가 2^5 즉, 32인 배열이 필요합니다.
물건을 줍는 과정에서 같은 칸을 밟을 수 있기 때문에 평소처럼 이차원 visited 배열을 사용하면 안되고 어떤 물건을 주웠는가까지 표시하는 삼차원 visited 배열을 사용해야했습니다.
따라서, visited 배열을 visited[MAX][MAX][1 << MAX_STUFF] 로 표시했습니다. BFS 탐색을 진행할 때는 다음 칸에 줍지 않은 물건 여부를 확인한 뒤 1. 줍지 않은 물건이 있다면 checked 변수에 비트 연산을 통해 주웠다고 표시하고 큐에 넣습니다. 2. 줍지 않은 물건이 없고 갈 수 있는 칸이라면 그대로 큐에 넣습니다. 3. 모든 물건을 주웠고 도착점에 도착한다면 time을 출력하고 프로그램을 종료합니다. 문제 조건에 모든 물건을 챙길 수 없는 경우는 주어지지 않는다. 라고 나와있기 때문에 해당 부분에 대해서는 예외처리를 하지 않았습니다. 개발환경:Visual Studio 2017 지적, 조언, 질문 환영입니다! 댓글 남겨주세요~ 반응형
[백준][C++] 17244 아맞다우산
www.acmicpc.net/problem/17244
알고리즘 종류
– 구현
– BFS
사고 과정
– 이 문제에서 중요한 조건은 재방문 처리이다. 특히 아래와 같은 상황이다. 시작점 S에서 빨간색 선으로 이동하고, 초록색선으로 이동한다. 이 때 초록색 화살표 끝의 X에서는 어떻게 재방문을 처리해야 할까?
– 일단, X를 구별할 수 없으니 번호를 붙여주기로 했다.
– 이제 비교해볼 상황이 있다.
1. 0을 방문했고 다시 0으로 오는 경우
2. 0을 방문했고 1을 방문한 뒤에 다시 0으로 오는 경우
– 위 2가지 경우에서 1번은 재방문을 할 수 없다. 그러나 2번은 재방문을 할 수 있다. 왜냐하면, 위 이미지에서 빨간색과 초록색 경로에 해당하는 경우이기 때문이다. 이런 재방문을 어떻게 처리할 수 있을까? Bit mask를 이용하면 쉽게 해결할 수 있다. 이 문제를 풀어보면 이해하기 쉬울 것이다.
– 2가지 경우를 비트로 나타내보자. 재방문 검사 배열은 isVisited[y][x][1<
#include < vector > #include < queue > #include < cstring > #include < string > using namespace std ; struct State{ int y, x; int bits = 0 ; int time = 0 ; }; int h, w; int sy, sx; int totalBits = 0 ; char mat[ 51 ][ 51 ]; int isVisited[ 51 ][ 51 ][ 1 < < 6 ]; int dir[ 4 ][ 2 ] = {{ 1 , 0 }, { 0 , 1 }, { - 1 , 0 }, { 0 , - 1 }}; bool isValid( int y, int x){ return (y > = 0 & & y < h) & & (x > = 0 & & x < w); } void solution(){ queue < State > q; // y, x , X의 bit의 합, 이동 시간 State s; s.y = sy; s.x = sx; q.push(s); while ( ! q.empty()){ State cs = q. front (); q. pop (); int cy = cs.y; int cx = cs.x; int ct = cs.time; int cb = cs.bits; for ( int d = 0 ; d < 4 ; d + + ){ int ny = cy + dir[d][ 0 ]; int nx = cx + dir[d][ 1 ]; // 모든 물건을 가지고 문에 도착하면 종료 if (mat[ny][nx] = = 'E' & & cb = = totalBits){ cout < < ct + 1 ; return ; } if ( ! isValid(ny, nx)) continue ; // 물건에 도착하면 if (mat[ny][nx] > = ‘0’ & & mat[ny][nx] < '5' ){ // 같은 물건을 가지고 같은 자리에 왔었는지 확인 int nb = cb | ( 1 < < mat[ny][nx] - '0' ); if ( ! isVisited[ny][nx][nb]){ isVisited[ny][nx][nb] = 1 ; State ns; ns.y = ny; ns.x = nx; ns.time = ct + 1 ; ns.bits = nb; q.push(ns); } } // 일반, 출입구, 시작점을 지나는 경우 // 출구가 그래프의 가운데 있을 수도 있어서 지나칠 수 있다. else if (mat[ny][nx] ! = '#' ){ if ( ! isVisited[ny][nx][cb]){ isVisited[ny][nx][cb] = 1 ; State ns; ns.y = ny; ns.x = nx; ns.time = ct + 1 ; ns.bits = cb; q.push(ns); } } } } } int main( void ){ ios_base::sync_with_stdio( 0 ); cin .tie( 0 ); cin > > w > > h; char mark = ‘0’ ; for ( int i = 0 ; i < h; i + + ){ for ( int j = 0 ; j < w; j + + ){ cin > > mat[i][j]; if (mat[i][j] = = ‘S’ ){ sy = i; sx = j; mat[i][j] = ‘.’ ; } else if (mat[i][j] = = ‘X’ ){ mat[i][j] = mark + + ; // X에 번호를 붙여준다. } } } // 모든 X를 더했을 때 최종 값을 구한다. // X가 3까지면 2^4-1이 최종 값이 된다. totalBits = ( 1 < < mark - '0' ) - 1 ; solution(); } Colored by Color Scripter cs 시행착오 - 첫 시도는 메모리 초과였다. 본인은 우선순위 큐를 이용해서 X를 방문한 개수 내림차순, 이동시간 오름차순으로 데이터를 저장하여 가장 먼저 X를 방문하면서 최단 시간을 찾으려고 했다. 그런데 재방문 처리를 하지 않았다. 제출에서 50%가 되면서 메모리 초과가 발생했다. - 배운 것이 있다면, 우선순위 큐에 compare를 만들어서 사용하는 방법이다. 아래에 시도했던 코드가 있다. 더보기 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 #include < iostream > #include < vector > #include < queue > #include < cstring > #include < string > using namespace std ; struct State{ int cnt = 0 ; int time = 0 ; int y, x; string check = “00000” ; }; struct cmp{ bool operator ()(State a, State b){ if (a.cnt ! = b.cnt) return a.cnt < b.cnt; else return a.time > b.time; } }; int h, w; int sy, sx, ey, ex; int thingCnt = 0 ; int answer = 0 ; char mat[ 51 ][ 51 ]; int isVisited[ 51 ][ 51 ]; int dir[ 4 ][ 2 ] = {{ 1 , 0 }, { 0 , 1 }, { – 1 , 0 }, { 0 , – 1 }}; vector < pair < int , int > > things; bool isValid( int y, int x){ return (y > = 0 & & y < h) & & (x > = 0 & & x < w); } void solution(){ priority_queue < State, vector < State > , cmp > pq; State s; s.y = sy; s.x = sx; pq.push(s); while ( ! pq.empty()){ State cs = pq.top(); pq. pop (); int cy = cs.y; int cx = cs.x; int ct = cs.time; int cc = cs.cnt; string cch = cs.check; for ( int d = 0 ; d < 4 ; d + + ){ int ny = cy + dir[d][ 0 ]; int nx = cx + dir[d][ 1 ]; if (mat[ny][nx] = = 'E' & & cc = = thingCnt){ answer = ct + 1 ; return ; } if ( ! isValid(ny, nx)) continue ; if (mat[ny][nx] = = '#' ) continue ; if (mat[ny][nx] > = ‘0’ & & mat[ny][nx] < '5' ){ int num = mat[ny][nx] - '0' ; if (cs.check[num] = = '0' ){ State ns; ns.y = ny; ns.x = nx; ns.cnt = cc + 1 ; ns.time = ct + 1 ; ns.check = cch; ns.check[num] = '1' ; pq.push(ns); } else { State ns; ns.y = ny; ns.x = nx; ns.cnt = cc; ns.time = ct + 1 ; ns.check = cch; pq.push(ns); } } else { State ns; ns.y = ny; ns.x = nx; ns.cnt = cc; ns.time = ct + 1 ; ns.check = cch; pq.push(ns); } } } } int main( void ){ ios_base::sync_with_stdio( 0 ); cin .tie( 0 ); cin > > w > > h; int mark = ‘0’ ; for ( int i = 0 ; i < h; i + + ){ for ( int j = 0 ; j < w; j + + ){ cin > > mat[i][j]; if (mat[i][j] = = ‘S’ ){ sy = i; sx = j; mat[i][j] = ‘.’ ; } else if (mat[i][j] = = ‘E’ ){ ey = i; ex = j; } else if (mat[i][j] = = ‘X’ ){ things. push_back ({i,j}); mat[i][j] = mark; mark + + ; thingCnt + + ; } } } solution(); cout < < answer < < endl ; } Colored by Color Scripter cs - 골드 3이상이 되면서 재방문 조건이 까다로워 지고 있다. 이번 문제에서는 비트 마스크를 이용한 재방문 조건 생성이다. A지점을 방문할 때, A에서 A로 오는 재방문은 방지 하지만, A에서 B를 갔다가 다시 A로 오는 재방문은 허락한다.
[백준] 17244번 : 아맞다우산
반응형
[BFS + 비트마스크]N x M 격자 맵에서 ‘X’로 표시된 모든 물건을 챙기고 탈출구 ‘E’로 최소한의 움직임으로 나가는 방법을 찾는 문제. 격자의 크기 제한이 최대 50×50이고 물건의 개수가 최대 5개라서 비트마스킹을 안써도 메모리적인 부분에서 큰 손실은 없을 것 같으나, 물건이 모두 ‘X’로 동일하여 현재 내가 특정 정점에 방문했을 때, 어떤 물건을 갖고 있는 지를 체크하는 것이 비트마스킹만큼 좋은 것이 없기에 비트마스킹을 사용했다.
먼저 입력을 받을 때 ‘X’인 곳을 ‘0’, ‘1’, ‘2’, …처럼 X가 아닌 숫자로 지정해놓는다. 이는 물건에 “인덱스”를 부여하는 효과를 가져오며 물건이 몇 개 존재하는지 또한 알아낼 수 있다.
int sY = 0, sX = 0; char idx = ‘0’; for(int i=1; i<=n; i++) { char[] str = br.readLine().toCharArray(); for (int j = 1; j <= m; j++) { map[i][j] = str[j - 1]; if (map[i][j] == 'X') { map[i][j] = idx++; k++; } else if (map[i][j] == 'S') { sY = i; sX = j; } } } 그럼 이제 지도에는 S, ., #, E, 0 ~ 4가 존재할 것이고, BFS를 시작점 S에서 부터 탐색을 한다. 1) '0', '1', '2', '3', '4' 일 때 현재 방문한 정점이 위의 값 중 하나라면, 물건이 있는 곳이다. 이때 내가 이미 해당 물건을 챙겼는지 여부를 비트마스킹으로 체크한다. 만약 이미 챙겼던 물건이라면 item은 변화를 주지 않고 그저 방문한다. 아직 챙기지 않은 물건이라면 챙기고 방문한다. if(map[ny][nx] >= ‘0’ && map[ny][nx] <= '5'){ int num = map[ny][nx] - '0'; if( (item & (1 << num)) == 0){ nItem = item | (1 << num); visit[ny][nx][nItem] = true; Q.add(new Point(ny, nx, move + 1, nItem)); continue; } } 2) '#'와 숫자를 제외한 나머지 이때는 그냥 방문하기만 하면 된다. # 종료 시퀀스 - 물건을 모두 챙겼는지? 현재 정점이 'E' 인지 # Code >
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.LinkedList; import java.util.Queue; import java.util.StringTokenizer; public class Main { static class Point{ int y, x, move, item; public Point(int yy, int xx, int m, int it){ y=yy; x=xx; move=m; item=it; } } //n : 높이, m : 너비, k : 물건의 개수 static int n, m, k; static int[] Y = {-1,1,0,0}, X={0,0,-1,1}; static char[][] map = new char[51][51]; static boolean[][][] visit = new boolean[51][51][(1 << 6)]; static int BFS(int sy, int sx) { Queue
Q = new LinkedList<>(); visit[sy][sx][0] = true; Q.add(new Point(sy, sx, 0, 0)); while(!Q.isEmpty()){ Point p = Q.poll(); int y = p.y; int x = p.x; int move = p.move; int item = p.item; if(map[y][x] == ‘E’ && item == ((1 << k) - 1)) return move; for(int a=0; a<4; a++){ int ny = y+Y[a]; int nx = x+X[a]; int nItem = 0; if(ny < 1 || nx < 1 || ny > n || nx > m || visit[ny][nx][item] || map[ny][nx] == ‘#’) continue; if(map[ny][nx] >= ‘0’ && map[ny][nx] <= '5'){ int num = map[ny][nx] - '0'; if( (item & (1 << num)) == 0){ nItem = item | (1 << num); visit[ny][nx][nItem] = true; Q.add(new Point(ny, nx, move + 1, nItem)); continue; } } visit[ny][nx][item] = true; Q.add(new Point(ny, nx, move + 1, item)); } } return 0; } public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st = new StringTokenizer(br.readLine()); m = Integer.parseInt(st.nextToken()); n = Integer.parseInt(st.nextToken()); int sY = 0, sX = 0; char idx = '0'; for(int i=1; i<=n; i++) { char[] str = br.readLine().toCharArray(); for (int j = 1; j <= m; j++) { map[i][j] = str[j - 1]; if (map[i][j] == 'X') { map[i][j] = idx++; k++; } else if (map[i][j] == 'S') { sY = i; sX = j; } } } System.out.println(BFS(sY, sX)); } } 반응형
[백준 17244] 아맞다우산 (Java)
728×90
반응형
문제 링크: https://www.acmicpc.net/problem/17244
1. 주의할 점
– 특정 지점에 방문했을 때, 서로 다른 물건의 조합을 가지고 접근한 경우 어떻게 처리할 것인지 생각한다
2. 구현
– 위의 주의할 점의 예시로, (1,1)을 방문할 때 [0,1]번 물건을 가지고 접근했을 때와 [1,2]번 물건을 가지고 접근했을 때를 구분하기 위해 비트마스크를 이용한다(비트마스크 접근을 위한 추가 힌트: 최대 5개의 물건)
– 집의 구조를 Int방식으로 받고, -1: 이동할 수 있는 루트, 0~4: 물건, 5: 벽으로 바꾼 후, BFS 탐색을 수행한다
– Check[y][x][key] 배열을 전부 Maxi로 초기화 하고 시작하며, Check 배열은 (y,x)에 key만큼의 물건을 가지고 있을때 도착한 최단거리를 저장한다
– BFS()를 수행하여 모든 물건을 챙기고 목표지점에 도달했을 때, 종료한다(시간단축 위해 구현했으나 없어도 AC를 받을거라고 생각합니다)
import java.util.*; import java.lang.*; import java.io.*; class Main { static class Info{ int y,x,val,knum; public Info(int y, int x, int val, int knum){ this.y=y; this.x=x; this.val=val; this.knum=knum; } }; static final int maxi = 5000; static final int dx[] = {0,1,0,-1}; static final int dy[] = {-1,0,1,0}; static int arr[][],check[][][]; static int row,col,keys,sy,sx,ey,ex; static void bfs(){ Info ii; Queue
q = new LinkedList<>(); q.offer(new Info(sy,sx,0,0)); check[sy][sx][0]=0; while(!q.isEmpty()){ ii = q.poll(); int cx = ii.x; int cy = ii.y; int cv = ii.val; int ck = ii.knum; if(cx==ex && cy==ey && ck==((1< =0 && ny>=0 && nx cv+1){ check[ny][nx][nk]=cv+1; q.offer(new Info(ny,nx,cv+1,nk)); } } } } } public static void main (String[] args) throws java.lang.Exception { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String str = br.readLine(); StringTokenizer st = new StringTokenizer(str); col = Integer.parseInt(st.nextToken()); row = Integer.parseInt(st.nextToken()); //초기화 keys=0; arr = new int[row][col]; check = new int[row][col][32]; for(int i=0;i
boj 17244 아맞다우산
https://www.acmicpc.net/problem/17244
챙겨야 하는 물건은 최대 5개이므로 bfs + 비트마스킹이 가능합니다.
visit[x][y][bit]: 좌표 (x, y)에 도착했을 때 찾은 물건의 비트가 bit인 경우의 방문 처리입니다.
비트를 어떻게 할지 고민하다가 chk배열을 사용하여 해당 좌표에 있는 물건의 비트를 정해주었습니다.
나가는 문에 도착했을 때 모든 물건을 찾았을 때만 t를 출력합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 #include < iostream > #include < queue > #define MAX 50 using namespace std ; typedef pair < pair < int , int > , int > pii; queue < pii > q; char list[MAX][MAX]; bool visit[MAX][MAX][ 1 < < 5 ]; int chk[MAX][MAX]; int direct[ 4 ][ 2 ] = { { 0 , 1 },{ 1 , 0 },{ 0 , - 1 },{ - 1 , 0 } }; int N, M, bit; void bfs() { for ( int t = 1 ; ! q.empty(); t + + ) { int qsize = q. size (); while (qsize - - ) { int x = q. front ().first.first; int y = q. front ().first.second; int cnt = q. front ().second; q. pop (); for ( int i = 0 ; i < 4 ; i + + ) { int nx = x + direct[i][ 0 ]; int ny = y + direct[i][ 1 ]; int ncnt = cnt; if (nx < 0 | | ny < 0 | | nx > = N | | ny > = M) continue ; if (list[nx][ny] = = ‘X’ ) { int b = chk[nx][ny]; ncnt | = b; } if (list[nx][ny] = = ‘#’ | | visit[nx][ny][ncnt]) continue ; if (list[nx][ny] = = ‘E’ & & ncnt = = bit) { cout < < t < < ' ' ; return ; } q.push({ {nx,ny}, ncnt }); visit[nx][ny][ncnt] = true ; } } } } void input() { int cnt = 0 ; cin > > M > > N; for ( int i = 0 ; i < N; i + + ) { for ( int j = 0 ; j < M; j + + ) { cin > > list[i][j]; if (list[i][j] = = ‘S’ ) { q.push({ {i,j}, 0 }); visit[i][j][ 0 ] = true ; } else if (list[i][j] = = ‘X’ ) { chk[i][j] = ( 1 < < cnt); cnt + + ; } } } bit = ( 1 < < cnt) - 1 ; } int main() { cin .tie( NULL ); cout .tie( NULL ); ios::sync_with_stdio( false ); input(); bfs(); return 0 ; } Colored by Color Scripter cs
키워드에 대한 정보 아 맞다 우산
다음은 Bing에서 아 맞다 우산 주제에 대한 검색 결과입니다. 필요한 경우 더 읽을 수 있습니다.
이 기사는 인터넷의 다양한 출처에서 편집되었습니다. 이 기사가 유용했기를 바랍니다. 이 기사가 유용하다고 생각되면 공유하십시오. 매우 감사합니다!
사람들이 주제에 대해 자주 검색하는 키워드 [천관사복] 진옥으로 비교당하는 아이
- 동영상
- 공유
- 카메라폰
- 동영상폰
- 무료
- 올리기
YouTube에서 아 맞다 우산 주제의 다른 동영상 보기
주제에 대한 기사를 시청해 주셔서 감사합니다 [천관사복] 진옥으로 비교당하는 아이 | 아 맞다 우산, 이 기사가 유용하다고 생각되면 공유하십시오, 매우 감사합니다.