본문 바로가기

c++/Baekjoon Online

백준 19237 : 어른 상어 C++

www.acmicpc.net/problem/19237

 

19237번: 어른 상어

첫 줄에는 N, M, k가 주어진다. (2 ≤ N ≤ 20, 2 ≤ M ≤ N2, 1 ≤ k ≤ 1,000) 그 다음 줄부터 N개의 줄에 걸쳐 격자의 모습이 주어진다. 0은 빈칸이고, 0이 아닌 수 x는 x번 상어가 들어있는 칸을 의미

www.acmicpc.net

풀이

1. 상어는 일단 shark라는 struct 만들어서 관리

 -> 생존 여부

 -> 현재 위치, 방향

 -> 방향 우선순위들

 

2. map은 두개만들어서 관리

 1) 상어들

 2) 채취 정보

  -> 누가 남겼는지, 몇턴 남았는지

 

3. 입력 다 받고 while문 돌린다. 탈출하는건 두가지!

 1) 상어가 1번만 남음

 2) 1000 이상! // 초과 아니다!!!!!!!!!!

      if (result > 1000) -> 이거로 했다가 30분 날려먹음

 

4. while 문 구성

 1) 지금 상어 위치에 채취 남기기

 2) 상어들 이동! ( 이때 겹치면 젤 큰놈만 살리고 그러면 된다 )

 3) 채취 다 -1

 4) result++ (몇턴 지났는지 여부)

 5) 탈출 조건 만족하는지 체크

 

 

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;

struct shark {
	int alive;
	int r, c, way;//지금 위치랑 방향
	int ways[4][4];//방향에 대한 우선순위
};
int map[21][21];//상어 위치
int back_up[21][21];
pair<int,int> map_smell[21][21];//채취 정보!!  어떤 상어, 남은 시간
shark sharks[401];
int n, m, k;
//n은 지도 m은 상어 마릿수 k는 냄새 지속시간


int d_r[4] = { -1,1,0,0 };//상 하 좌 우
int d_c[4] = { 0,0,-1,1 };


void move_shark()
{
	memset(back_up, 0, sizeof(back_up));
	for (int i = 1; i <= m; i++)
	{
		if (sharks[i].alive == 0)//죽은놈 재껴
			continue;

		int flag = 0;
		shark temp = sharks[i];

		//냄새 없는 칸
		for (int k = 0; k < 4; k++)
		{
			int new_r = temp.r + d_r[temp.ways[temp.way][k]];//지금 방향의 우선순위 순서대로
			int new_c = temp.c + d_c[temp.ways[temp.way][k]];

			if (new_r < 0 || new_c < 0 || new_r >= n || new_c >= n)
				continue;

			if (map_smell[new_r][new_c].second == 0)//채취없는 칸이면 이동!!
			{
				sharks[i].r = new_r;
				sharks[i].c = new_c;
				sharks[i].way = temp.ways[temp.way][k];

				if (back_up[new_r][new_c] == 0)//아무도 없어!
				{
					back_up[new_r][new_c] = i;
					back_up[temp.r][temp.c] = 0;
					flag = 1;
					break;
				}
				else if( back_up[new_r][new_c] !=0)
				{
					//다음에 들어올 놈이 무조건 숫자 큼
					sharks[i].alive = 0;
					flag = 1;
					break;
				}
			}
		}

		if (flag == 1)
			continue;

		//냄새 없는칸 없으면!
		for (int k = 0; k < 4; k++)
		{
			int new_r = temp.r + d_r[temp.ways[temp.way][k]];//지금 방향의 우선순위 순서대로
			int new_c = temp.c + d_c[temp.ways[temp.way][k]];

			if (new_r < 0 || new_c < 0 || new_r >= n || new_c >= n)
				continue;

			if (map_smell[new_r][new_c].first == i)//내가 남긴 채취
			{
				sharks[i].r = new_r;
				sharks[i].c = new_c;
				sharks[i].way = temp.ways[temp.way][k];

				if (back_up[new_r][new_c] == 0)//아무도 없어!
				{
					back_up[new_r][new_c] = i;
					back_up[temp.r][temp.c] = 0;
					flag = 1;
					break;
				}
				else if (back_up[new_r][new_c] != 0)
				{
					//다음에 들어올 놈이 무조건 숫자 큼
					sharks[i].alive = 0;
					flag = 1;
					break;
				}
			}
		}

	}

	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
			map[i][j] = back_up[i][j];

}


int main()
{
	memset(map_smell, 0, sizeof(map_smell));
	memset(map, 0, sizeof(map));
	int a;
	cin >> n >> m >> k;

	for(int i=0;i<n;i++)
		for (int j = 0; j < n; j++)
		{
			cin >> map[i][j];
			if (map[i][j] != 0)
			{
				sharks[map[i][j]].r = i;
				sharks[map[i][j]].c = j;
			}
		}

	for (int i = 1; i <= m; i++)
	{
		cin >> a;
		sharks[i].way = a - 1;
		sharks[i].alive = 1;
	}

	for (int i = 1; i <= m; i++)
	{
		for(int j=0;j<4;j++)
			for (int f = 0; f < 4; f++)
			{
				cin >> a;
				sharks[i].ways[j][f] = a - 1;
			}
	}


	int result = 0;

	while (true)
	{
		

		//지금 자리에 채취 남기기
		for (int i = 1; i <= m; i++)
		{
			if (sharks[i].alive == 0)//죽은 놈이면 패쓰요
				continue;
			//i 번째 상어가 채취 남겨요~
			map_smell[sharks[i].r][sharks[i].c].first = i;
			map_smell[sharks[i].r][sharks[i].c].second = k;
		}

		//이동 + 방향 바꿔주기
		move_shark();

		//채취 다 마이너스 1!
		for(int i=0;i<n;i++)
			for (int j = 0; j < n; j++)
			{
				if (map_smell[i][j].second != 0)
				{
					map_smell[i][j].second--;
					if (map_smell[i][j].second == 0)
					{
						map_smell[i][j].first = 0;
					}
				}
			}

		result++; //한턴 지나면!

		int flag = 0;

		for (int i = 0; i < n; i++)
			for (int j = 0; j < n; j++)
			{
				if (map[i][j] != 0 && map[i][j] != 1)
					flag = 1;
			}

		if (flag == 0)//상어 한마리만 남는경우!
			break;

		if (result >= 1000)//1000넘어가면 바아로 -1
		{
			cout << -1 << endl;
			return 0;
		}
	}

	cout << result << endl;

	return 0;
}

 

 

 

 

'c++ > Baekjoon Online' 카테고리의 다른 글

백준 : 퇴사 c++  (0) 2020.11.18
백준 1938 : 통나무 옮기기 c++  (0) 2020.10.16
백준 19238 : 스타트 택시 c++  (0) 2020.10.15
백준 17142 c++ : 연구소 3  (0) 2020.10.11
백준 1726 : 로봇 c++  (0) 2020.10.10