Algorithm/문제풀이

[BFS] 아기 상어

lee308812 2019. 10. 24. 23:02

 

 

 

예제 입력 1

3

0 0 0

0 0 0

0 9 0

예제 출력 1

0

예제 입력 2

3

0 0 1

0 0 0

0 9 0

예제 출력 2

3

예제 입력 3

4

4 3 2 1

0 0 0 0

0 0 9 0

1 2 3 4

예제 출력 3

14

예제 입력 4

6

5 4 3 2 3 4

4 3 2 3 4 5

3 2 9 5 6 6

2 1 2 3 4 5

3 2 1 6 5 4

6 6 6 6 6 6

예제 출력 4

60

예제 입력 5

6

6 0 6 0 6 1

0 0 0 0 0 2

2 3 4 5 6 6

0 0 0 0 0 2

0 2 0 0 0 0

3 9 3 0 0 1

예제 출력 5

48

예제 입력 6

6

1 1 1 1 1 1

2 2 6 2 2 3

2 2 5 2 2 3

2 2 2 4 6 3

0 0 0 0 0 6

0 0 0 0 0 9

예제 출력 6

39

 

 

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

 

16236번: 아기 상어

N×N 크기의 공간에 물고기 M마리와 아기 상어 1마리가 있다. 공간은 1×1 크기의 정사각형 칸으로 나누어져 있다. 한 칸에는 물고기가 최대 1마리 존재한다. 아기 상어와 물고기는 모두 크기를 가지고 있고, 이 크기는 자연수이다. 가장 처음에 아기 상어의 크기는 2이고, 아기 상어는 1초에 상하좌우로 인접한 한 칸씩 이동한다. 아기 상어는 자신의 크기보다 큰 물고기가 있는 칸은 지나갈 수 없고, 나머지 칸은 모두 지나갈 수 있다. 아기 상어는 자신의 크

www.acmicpc.net

- BFS를 여러번 돌려야한다.

- 먼저 BFS 돌려서 가장 가까운 먹을 수 있는 1개의 물고기의 위치를 가져온다. 여러개일 경우 같은 거리이면 가장 위/왼쪽이 우선이라고 했으므로 정렬해서 첫번째것만 가져오면 된다.

- 현재 위치를 잡아먹은 물고기가 있는 곳으로 업데이트하고 물고기 잡아먹는 처리를 한다. (경험치(?), size 업데이트)

- 더이상 잡아먹을 수 있는 물고기가 없을 때까지 반복한다.

 

#include <stdio.h>



const int MAX_SIZE = 20;
const int MAX_QUEUE_SIZE = 1000;

int map[MAX_SIZE][MAX_SIZE];

int N;

int dR[] = { -1, 1, 0, 0 };
int dC[] = { 0, 0, -1, 1 };

class Point
{
public:
	int r;
	int c;
	int dist;

	Point() {
		r = c = dist = 0;
	}

	Point(int r, int c) : r(r), c(c) {}

	bool isInBoundary(int N)
	{
		return (r >= 0) && (r < N) && (c >= 0) && (c < N);
	}

	bool operator<=(Point other)
	{
		if (r == other.r) return c <= other.c;
		return r <= other.r;
	}

	bool operator==(Point other)
	{
		return (r == other.r) && (c == other.c);
	}
};

class Shark : public Point
{
public:
	int size;
	int exp; 

	Shark()
	{
		r = c = 0;
		size = 2;
		exp = 0;
	}

	Shark(int r, int c, int size, int weight) : size(size), exp(exp)
	{
		this->r = r;
		this->c = c;
	}

	void eatFish(int r, int c)
	{
		
	}
};
template<typename T>
class vector
{
public:
	T items[MAX_QUEUE_SIZE];
	int size;

	vector() { size = 0; }

	void add(T item)
	{
		items[size] = item;
		size++;
	}

	void clear()
	{
		size = 0;
	}

	void mergeSort(int start, int end)
	{
		if (start >= end) return;
		int mid = (start + end) / 2;

		mergeSort(start, mid);
		mergeSort(mid + 1, end);

		int i = start;
		int j = mid + 1;
		int k = 0;

		while (i <= mid && j <= end)
		{
			if (items[i] <= items[j])
			{
				tempItems[k] = items[i];
				i++; k++;
			}
			else
			{
				tempItems[k] = items[j];
				j++; k++;
			}
		}

		while (i <= mid)
		{
			tempItems[k] = items[i];
			i++; k++;
		}

		while (j <= end)
		{
			tempItems[k] = items[j];
			j++; k++;
		}

		for (int i = start; i <= end; i++)
		{
			items[i] = tempItems[i - start];
		}
	}

private:
	T tempItems[MAX_QUEUE_SIZE];
};


template <typename T>
class Queue
{
private:
	int front;
	int rear;
	T items[MAX_QUEUE_SIZE];

public:
	Queue() { front = rear = 0; }

	void push(T item)
	{
		items[rear] = item;
		rear = (rear + 1) % MAX_QUEUE_SIZE;
	}

	T pop()
	{
		T result = items[front];
		front = (front + 1) % MAX_QUEUE_SIZE;

		return result;
	}

	bool isEmpty()
	{
		return front == rear;
	}
};
Queue<Shark> q;
Shark shark;
Point nop(-1, -1);

Point BFS(Shark shark, int N)
{
	int dist[MAX_SIZE][MAX_SIZE];
	int minDist = -1;

	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N; j++)
		{
			dist[i][j] = -1;
		}
	}

	dist[shark.r][shark.c] = 0;
	q.push(shark);

	vector<Shark> targets;

	while (!q.isEmpty())
	{
		Shark now = q.pop();

		for (int i = 0; i < 4; i++)
		{
			Shark next(now.r + dR[i], now.c + dC[i], now.size, now.exp);

			if (!next.isInBoundary(N)) continue;

			if (map[next.r][next.c] == 0 && dist[next.r][next.c] == -1)
			{
				dist[next.r][next.c] = dist[now.r][now.c] + 1;
				q.push(next);
			}
			else if (map[next.r][next.c]!=0 && map[next.r][next.c] <= now.size && dist[next.r][next.c] == -1)
			{
				// 먹을 수 있다.
				if (map[next.r][next.c] < now.size)
				{
					if (minDist == -1 || minDist > dist[now.r][now.c]+1)
					{
						targets.clear();
						minDist = dist[now.r][now.c] + 1;
						targets.add(next);
					}
					else if (minDist == dist[now.r][now.c]+1)
					{
						minDist = dist[now.r][now.c] + 1;
						targets.add(next);
					}
				}
					
				dist[next.r][next.c] = dist[now.r][now.c] + 1;
				q.push(next);
			}
		}
	}

	if (targets.size == 0)
	{
		return nop;
	}
	
	targets.mergeSort(0, targets.size-1); // 가장 왼쪽 위를 찾음
	targets.items[0].dist = minDist;

	return targets.items[0];
}

int main(void)
{
	scanf("%d", &N);

	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N; j++)
		{
			scanf("%d", &map[i][j]);
			
			if (map[i][j] == 9)
			{
				shark.r = i;
				shark.c = j;
				
				map[i][j] = 0;
			}
		}
	}

	int result = 0;

	while (true)
	{
		// 먹을 수 있는 물고기를 찾는다.
		Point target = BFS(shark, N);

		if (target == nop)
		{
			break;
		}
		else
		{
			// 물고기를 먹는다.
			shark.r = target.r;
			shark.c = target.c;
			shark.exp++;

			result += target.dist;

			if (shark.exp >= shark.size)
			{
				shark.exp -= shark.size;
				shark.size++;
			}

			map[target.r][target.c] = 0;
		}
	}

	printf("%d\n", result);

	return 0;
}

 

'Algorithm > 문제풀이' 카테고리의 다른 글

[BFS] 적록색약  (0) 2019.10.29
[BFS] 레이저 통신  (0) 2019.10.29
[BFS] 탈출  (0) 2019.10.24
[BFS] 움직이는 미로 탈출  (0) 2019.10.23
[BFS] 벽 부수고 이동하기 3  (0) 2019.10.19