BOJ 19237, 어른 상어
Source: BOJ 19237 어른 상어
어른 상어
변수를 어떻게 잡는냐가 관건이었던 문제였다
푸는데 3시간이 걸린건 안비밀..
문제를 요약해보자면 n x n 보드판위에 m 개의 상어가 있고 각각의 상어는 현재 방향과
다음칸으로 이동해야 할 때의 방향 우선순위를 가진다
방향: 1, 2, 3, 4는 각각 위, 아래, 왼쪽, 오른쪽을 의미한다.
상어는 방향 우선순위를 고려하여 빈칸으로의 이동을 우선순위로 갖고, 빈칸이 없다면 자신의 냄새가 있는 칸으로 이동한다
(마찬가지로 방향우선순위를 고려함)
만약 서로 다른 상어가 같은 한 칸에서 만나게 된다면 index가 작은 상어가 남고 다른 상어는 격자판 밖으로 나간다
PS Logic
- SHARK라는 구조체를 만들고 그안에 priority라는 2차원 배열을 만들어 각 방향에 대한 다음방향 우선순위를 저장한다
- 3차원 board를 만들고 각 칸안에 두개의 값 (상어의 number, 남은 유효시간)을 저장한다
- 입력으로 주어지는 값들을 초기값으로 저장한다
- while문 안에서 상어의 현재 위치, 방향을 찾고 그에 따른 다음위치, 다음 방향을 탐색한다
- 다음 방향이 빈칸이라면 그 위치로 상어가 이동한다 (방향 우선순위 고려) (shark.x, shark.y, shark.dir 업데이트) (냄새 추가)
- 인접한 칸에 빈칸이 없으면 상어는 자신의 냄새가 있는 칸으로 이동한다 (방향 우선순위 고려) (shark.x, shark.y, shark.dir 업데이트) (냄새 추가)
- m개의 상어 중, 같은 좌표를 저장하고 있는 상어를 찾고 number가 큰 상어는 격자판 밖으로 제외시킨다
- 보드판위에 모든 냄새가 있는 칸에 유효시간에 1을 뺀다
- 현재 상어가 있는 칸도 1을 뺐으므로 현재 상어가 있는 칸은 1을 다시 더해줘야한다
- 반복!
코드에 주석을 열심히 작성했으므로 주석을 보면서 코드를 참고하기 바란다
#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second
//위 아래 왼쪽 오른쪽
int dx[4] = {-1, 1, 0, 0};
int dy[4] = {0, 0, -1, 1};
struct SHARK
{
int x, y;
int dir;
int priority[4][4];
};
SHARK shark[401];
//상어 num 1~M, 1이 가장강함
//냄새 k번 이동하면 사라짐
int n, m, k;
int board[20][20][2]; // 상어의 NUM, 남은 유효시간
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cin >> n >> m >> k;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
cin >> board[i][j][0];
if (board[i][j][0] != 0)
{
board[i][j][1] = k;
shark[board[i][j][0]].x = i;
shark[board[i][j][0]].y = j;
}
}
}
// m개의 상어, 방향 입력
for (int i = 1; i <= m; i++)
{
int d;
cin >> d;
d--;
shark[i].dir = d;
}
//각 상어의 방향에 대한 우선순위 방향 입력
for (int s = 1; s <= m; s++)
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
int dir;
cin >> dir;
dir--;
shark[s].priority[i][j] = dir;
}
}
}
int test = 15;
int time = 0;
int flag = false;
while (time <= 1000 && !flag)
{
time++;
for (int s = 1; s <= m; s++)
{
//상어의 현재위치, 방향
if (shark[s].x == -1)
continue;
int cx = shark[s].x;
int cy = shark[s].y;
int cd = shark[s].dir;
bool empty = false;
//상어의 다음위치, 방향
for (int i = 0; i < 4; i++)
{
int nd = shark[s].priority[cd][i];
int nx = cx + dx[nd];
int ny = cy + dy[nd];
if (nx < 0 || ny < 0 || nx >= n || ny >= n)
continue;
if (board[nx][ny][0] == 0)
{
//상어의 이동 처리
empty = true;
shark[s].x = nx;
shark[s].y = ny;
shark[s].dir = nd;
break;
}
}
// 냄새가 있는 칸으로 이동
if (!empty)
{
for (int i = 0; i < 4; i++)
{
int nd = shark[s].priority[cd][i];
int nx = cx + dx[nd];
int ny = cy + dy[nd];
if (nx < 0 || ny < 0 || nx >= n || ny >= n)
continue;
if (board[nx][ny][0] == s && board[nx][ny][1]>0)
{
shark[s].x = nx;
shark[s].y = ny;
shark[s].dir = nd;
break;
}
}
}
}
//같은 칸에 있는 상어 처리
for (int s = 1; s <= m; s++)
{
if(shark[s].x == -1) continue;
int x = shark[s].x;
int y = shark[s].y;
for (int t = s + 1; t <= m; t++)
{
if (x == shark[t].x && y == shark[t].y)
{
shark[t].x = -1;
shark[t].y = -1;
}
}
board[shark[s].x][shark[s].y][0] = s;
board[shark[s].x][shark[s].y][1] = k;
}
int cnt = 0;
for(int s = 1; s<=m; s++){
if(shark[s].x != -1) cnt++;
}
if (cnt == 1)
{
flag = true;
break;
}
//냄새 유효시간 처리
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (board[i][j][1] == 0)
{board[i][j][0] = 0;
continue;}
board[i][j][1]--;
if(board[i][j][1] == 0){
board[i][j][0] = 0;
}
}
}
//유효시간 전체를 1 뺐으므로 현재 상어가 있는칸은 1을 다시 더해줘야한다.
for(int s = 1; s<=m; s++){
board[shark[s].x][shark[s].y][1]++;
}
}
int ans = 0;
ans = (time>1000) ? -1 : time;
cout << ans;
return 0;
}
Leave a comment