nukw0n
찐이의 개발 연결구과
nukw0n
전체 방문자
오늘
어제
  • 분류 전체보기 (38)
    • 유연해지기 (21)
      • React.js (11)
      • Javascript (5)
      • webpack & babel (1)
      • etc. (4)
      • Next.js (0)
    • 단단해지기 (13)
      • Algorithm (9)
      • Computer Science (4)
    • 속닥속닥 (4)
    • 책읽는 남자 (0)

블로그 메뉴

    공지사항

    인기 글

    태그

    • Error Boundary
    • 프로그래머스
    • useBuiltIns
    • javascript
    • React 18
    • dfs
    • Batching
    • 알고리즘
    • fallback UI
    • intersectionobserver api
    • error 안 뜸
    • history API
    • 백준
    • vallia 라우터
    • vanilla spa
    • bfs
    • Auto Batching
    • 콜백 ref
    • sass vs postcss
    • React

    최근 댓글

    최근 글

    티스토리

    hELLO · Designed By 정상우.
    nukw0n

    찐이의 개발 연결구과

    [백준/BOJ 알고리즘] 16236 아기상어 C++
    단단해지기/Algorithm

    [백준/BOJ 알고리즘] 16236 아기상어 C++

    2020. 9. 17. 19:13

    > www.acmicpc.net/problem/16236

     

    16236번: 아기 상어

    N×N 크기의 공간에 물고기 M마리와 아기 상어 1마리가 있다. 공간은 1×1 크기의 정사각형 칸으로 나누어져 있다. 한 칸에는 물고기가 최대 1마리 존재한다. 아기 상어와 물고기는 모두 크기를 가��

    www.acmicpc.net

    아기 상어가 바다에서 엄마 상어 없이 얼마나 물고기를 잡아먹으며 버틸 수 있는가.. 하는 문제이다. 뚜루뚜두둡.

    더 이상 먹을 물고기가 없을 때까지의 시간을 계산하여 출력하면 된다! 문제 조건이 생각보다 까다롭고 이해하기 어려워서 좀 헤맸던 문제이다...

    처음엔 좌표와 비용을 갖는 이중pair(?) 자료형을 큐에 넣고 작업했는데, 시간초과가 나서 비용 정보를 갖는 배열을 생성해서 해결했다.

     

    문제의 핵심 

    • N의 최대값은 20이다. 무식하게 풀어도 가능하다.
    • 물고기를 잡아먹었으면 그 자리를 0으로 만들어주어야한다.
    • 몸집이 같으면 먹을 수 없다. 하지만 지나갈 수는 있다.
    • 먹을 수 있는 물고기가 여럿이라면, 조건에 맞는 물고기를 먹어야한다. 
      • 거리가 가까운 물고기가 최우선순위이다.
      • 거리가 같은 물고기가 여럿이라면, 그 중 가장 위에서 왼쪽에 있는 물고기를 먹어야한다.
    • 이동 비용을 계산하기 위한 별도의 공간이 필요하다.
    • 먹을 수 있는 물고기를 발견했다고 바로 먹는 것이 아니다.
    • 먹을 수 있는 물고기 중 최적의 조건에 있는 물고기를 먹어야하는 문제이다.

    구현  

    • 상어의 위치부터 시작해서 BFS 탐색을 시작한다.
    • cost = costMap[현재좌표] +1 의 방식으로 현재 좌표까지 오는 데 드는 비용을 계산한다.
    • 상어의 상하좌우를 탐색하며 조건에 따라 처리한다.
      • 이동하려는 곳에 본인보다 작은 물고기가 있다면,
        • 1. 현재의 비용(min_cost)을 변수에 저장한다. 이 비용은 물고기를 먹을 수 있는 최저비용 값이다.
        • 2. 큐에 현재 좌표 푸쉬 후 방문처리한다.
        • 3. costMap[현재좌표]에 비용을 저장한다. 
      • 이동하려는 곳에 본인과 크기가 같은 물고기가 있거나, 빈 칸일 경우,
        • 1. 큐에 현재 좌표 푸쉬 후 방문처리한다.
        • 2. costMap[현재좌표]에 비용을 저장한다.
    • cost가 min_cost보다 커질 경우 물고기를 먹는다.
      • '가장 위에 있는 물고기, 그러한 물고기가 여럿이라면, 가장 왼쪽에 있는 물고기를 먹는다' 의 조건을 만족하기 위해서 costMap 배열을 for문을 통해 위의 왼쪽에서부터 탐색하여 min_cost 값을 갖는 물고기를 찾는다.
      • cost를 전체 비용에 추가하고, 현재 크기에서 먹은 물고기의 값을 증가시켜준다. 레벨업할만큼 먹었다면 크기를 올려준다.
      • 비용, 방문처리 배열과 큐를 초기화하고, 먹은 물고기의 위치에서부터 다시 탐색을 시작한다.

     

     

     

     

    > 코드가 궁금하다면, 포스트 하단의 더보기를 눌러주세요

     

     

    * 코드에 대한 피드백은 언제나 환영합니다. *

    더보기
    #include <iostream>
    #include <queue>
    #include <algorithm>
    #include <cstring>
    #define pb push_back
    #define mp make_pair
    #define st first
    #define nd second
    #define lli long long int
    #define MAX 21
    using namespace std;
    typedef pair<int ,int> p;
    
    int map[MAX][MAX] = {};
    int visited[MAX][MAX] = {};
    int costMap[MAX][MAX] = {};
    int dir[4][2] = {{-1,0}, {0,-1}, {0,1}, {1,0}};
    queue<p> q;
    
    void clearQ() {
    	while(!q.empty()) q.pop();
    }
    
    p eat(int n, int size, int min) {
    	for(int i=1;i<=n;i++) {
    		for(int j=1;j<=n;j++) {
    			if(map[i][j] < size && map[i][j] && costMap[i][j] == min) {
    				map[i][j] = 0;
    				return mp(i,j);
    			}
    		}
    	}
    }
    
    void solve(int n, p shark) {
    	int cost = 0, ans = 0, evol = 2, size = 2, min_cost = 999;
    	int dx, dy;
    	p cur, best;
    	q.push(shark);
    	visited[shark.st][shark.nd] = 1;
    	while(!q.empty()) {
    		cur = q.front();
    		q.pop();
    		cost = costMap[cur.st][cur.nd] + 1;
    		if(cost > min_cost) {
    			best = eat(n, size, min_cost);
    			ans += min_cost;
    			if(!(--evol)) evol = ++size;
    			cost = 0;
    			memset(visited, 0, sizeof(visited));
    			memset(costMap, 0, sizeof(costMap));
    			clearQ();
    			q.push(best);
    			visited[best.st][best.nd] = 1;
    			min_cost = 999;
    			continue;
    		}
    		for(int i=0;i<4;i++) {
    			dx = cur.st + dir[i][0];
    			dy = cur.nd + dir[i][1];
    
    			if(visited[dx][dy] || dx < 1 || dy < 1 || dx > n || dy > n) continue;
    			if(map[dx][dy] && map[dx][dy] < size) { 
    				min_cost = cost;
    				q.push(mp(dx,dy));
    				visited[dx][dy] = 1;
    				costMap[dx][dy] = cost;
    			}
    			else if(!map[dx][dy] || map[dx][dy] == size) {
    				q.push(mp(dx,dy));
    				visited[dx][dy] = 1;
    				costMap[dx][dy] = cost;
    			}
    		}
    	}
    	cout << ans;
    } 
    
    int main(){
      ios::sync_with_stdio(0);
      cin.tie(0);
    	int n;
    	cin >> n;
    	p shark;
    	for(int i=1;i<=n;i++) {
    		for(int j=1;j<=n;j++) {
    			cin >> map[i][j];
    			if(map[i][j] == 9) {
    				shark = mp(i,j);
    				map[i][j] = 0;
    			}
    		}
    	} 
    	solve(n, shark);
    }

     

     

    '단단해지기 > Algorithm' 카테고리의 다른 글

    [백준/BOJ 알고리즘] 17845 수강 과목 C++  (0) 2021.09.12
    [백준/BOJ 알고리즘] 10830 행렬 제곱 C++  (0) 2021.09.12
    [백준/BOJ 알고리즘] 1039 교환 C++  (1) 2020.09.10
    [백준/BOJ 알고리즘] 2573 빙산 C++  (1) 2020.09.07
    [백준/BOJ 알고리즘] 3190 뱀 C++  (0) 2020.09.02
      '단단해지기/Algorithm' 카테고리의 다른 글
      • [백준/BOJ 알고리즘] 17845 수강 과목 C++
      • [백준/BOJ 알고리즘] 10830 행렬 제곱 C++
      • [백준/BOJ 알고리즘] 1039 교환 C++
      • [백준/BOJ 알고리즘] 2573 빙산 C++
      nukw0n
      nukw0n
      프론트엔드 개발자 권혁진입니다.

      티스토리툴바