https://www.acmicpc.net/problem/16236
N×N 크기의 공간에 물고기 M마리와 아기 상어 1마리가 있다. 공간은 1×1 크기의 정사각형 칸으로 나누어져 있다. 한 칸에는 물고기가 최대 1마리 존재한다.
아기 상어와 물고기는 모두 크기를 가지고 있고, 이 크기는 자연수이다. 가장 처음에 아기 상어의 크기는 2이고, 아기 상어는 1초에 상하좌우로 인접한 한 칸씩 이동한다.
아기 상어는 자신의 크기보다 큰 물고기가 있는 칸은 지나갈 수 없고, 나머지 칸은 모두 지나갈 수 있다. 아기 상어는 자신의 크기보다 작은 물고기만 먹을 수 있다. 따라서, 크기가 같은 물고기는 먹을 수 없지만, 그 물고기가 있는 칸은 지나갈 수 있다.
아기 상어가 어디로 이동할지 결정하는 방법은 아래와 같다.
아기 상어의 이동은 1초 걸리고, 물고기를 먹는데 걸리는 시간은 없다고 가정한다. 즉, 아기 상어가 먹을 수 있는 물고기가 있는 칸으로 이동했다면, 이동과 동시에 물고기를 먹는다. 물고기를 먹으면, 그 칸은 빈 칸이 된다.
아기 상어는 자신의 크기와 같은 수의 물고기를 먹을 때 마다 크기가 1 증가한다. 예를 들어, 크기가 2인 아기 상어는 물고기를 2마리 먹으면 크기가 3이 된다.
공간의 상태가 주어졌을 때, 아기 상어가 몇 초 동안 엄마 상어에게 도움을 요청하지 않고 물고기를 잡아먹을 수 있는지 구하는 프로그램을 작성하시오.
첫째 줄에 공간의 크기 N(2 ≤ N ≤ 20)이 주어진다.
둘째 줄부터 N개의 줄에 공간의 상태가 주어진다. 공간의 상태는 0, 1, 2, 3, 4, 5, 6, 9로 이루어져 있고, 아래와 같은 의미를 가진다.
아기 상어는 공간에 한 마리 있다.
첫째 줄에 아기 상어가 엄마 상어에게 도움을 요청하지 않고 물고기를 잡아먹을 수 있는 시간을 출력한다.
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
|
#include <iostream>
#include <string.h>
#include <queue>
using namespace std;
int n, cnt, len,MAP[21][21], dist[21][21], mx[] = {-1,0,1,0}, my[] = {0,1,0,-1};
int sx, sy, tx, ty, shark = 2, eat;
bool visit[21][21];
bool scan(int x, int y)
{
bool ret = false;
queue<pair<int, int> >q;
q.push({x,y});
visit[x][y] = true;
dist[x][y] = 0;
while(!q.empty())
{
int a = q.front().first;
int b = q.front().second;
q.pop();
for(int i=0;i<4;i++)
{
int nx = a + mx[i];
int ny = b + my[i];
if(nx<0||ny<0||nx>=n||ny>=n || visit[nx][ny] || MAP[nx][ny] > shark) continue;
if(dist[nx][ny] > dist[a][b] + 1) dist[nx][ny] = dist[a][b] + 1;
visit[nx][ny] = true;
q.push({nx,ny});
}
}
len = 9999;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
if(MAP[i][j] < shark && MAP[i][j] != 0 && len > dist[i][j])
{
tx = i;
ty = j;
len = dist[i][j];
ret = true;
}
return ret;
}
int solve()
{
int ans = 0;
while(cnt--)
{
memset(visit, false, sizeof(visit));
memset(dist, 60, sizeof(dist));
if(!scan(sx,sy)) break;
eat++;
MAP[tx][ty] = 0;
sx = tx;
sy = ty;
ans += len;
if(eat == shark)
{
eat = 0;
shark ++;
}
}
return ans;
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
cin>>MAP[i][j];
if(MAP[i][j] == 9)
{
sx = i;
sy = j;
MAP[i][j] = 0;
}
else if(MAP[i][j] != 0)
cnt++;
}
cout<<solve();
return 0;
}
|
cs |
문제 설명 잘못 이해해서 두시간 가까이 걸렸다...
예제에 설명 좀 해주지...
1. 입력을 받을 때 처음 상어의 위치와 먹어야 할 물고기의 개수를 저장
2. 물고기의 개수만큼 먹이 활동을 한다. 이 때, 더 이상 먹을 수 없는 상태가 되면 도중에 그만한다.
scan 이 여기서 나중에 먹을 고기를 찾는 함수다.
3. 현재 위치에서 방문할 수 있는 모든 곳(물고기의 크기가 자기 보다 작은 곳 이거나 물고기가 없는 곳의 거리를 모두 bfs로 저장.
4. bfs로 저장된 거리 행렬 탐색, 물고기를 먹을 수 있고, 거리가 가장 짧은 곳 서치.
4를 하면서 조건에 맞는 것이 없으면 false를 반환 (현 상황에서 먹을 수 있는 물고기 없음)
5. 먹은 위치 0으로 바꿔주고 위치 갱신한 다음에 거리 더하기, 이 때 먹은 물고기 갯수와 shark 크기 같으면 eat = 0, shark += 1 해주기
2589. 보물섬 GOLD V (C++) (0) | 2020.05.04 |
---|---|
2668. 숫자 고르기 GOLD V(C++) (0) | 2020.05.04 |
14889. 스타트와 링크 SILVERIII (C++) (0) | 2020.05.02 |
2023. 신기한 소수 GOLD V(C++) (0) | 2020.05.01 |
3187. 양치기 꿍 SILVER II(C++) (0) | 2020.05.01 |
댓글 영역