일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- CSV
- SWEA
- Vue.js
- DFS
- SQL
- gpdb
- 모의SW역량테스트
- aws
- Priority Queue
- JavaScript
- Trie
- 알고리듬
- 코테
- spring boot
- Bruth Force
- GitHub
- programmers
- 코딩테스트
- hash table
- 알고리즘
- 구현
- BFS
- Data Structure
- Python
- django
- boj
- Back tracking
- 시뮬레이션
- Algorithm
- Linked list
- Today
- Total
hotamul의 개발 이야기
[Algorithm][C++] BOJ 17143 낚시왕 본문
[Algorithm][C++] BOJ 17143 낚시왕
hotamul 2021. 9. 13. 23:26url: https://www.acmicpc.net/problem/17143
17143번: 낚시왕
낚시왕이 상어 낚시를 하는 곳은 크기가 R×C인 격자판으로 나타낼 수 있다. 격자판의 각 칸은 (r, c)로 나타낼 수 있다. r은 행, c는 열이고, (R, C)는 아래 그림에서 가장 오른쪽 아래에 있는 칸이다.
www.acmicpc.net
풀이 핵심
1. 상어가 벽을 만났을 때 방향 전환을 쉽게 하기 위해 dr, dc 배열과 GetReverseDir 함수를 이용한다.
const int dr[] = { 0,-1,1,0,0 };
const int dc[] = { 0,0,0,1,-1 };
// 1-->Up, 2--> Down, 3-->Right, 4-->Left
int GetReverseDir(int idx) {
if (idx == 1) return 2;
if (idx == 2) return 1;
if (idx == 3) return 4;
return 3;
}
2. 상어의 속도 (1초에 이동할 수 있는 거리)가 1000 이하의 숫자 이기 때문에 작지 않은 숫자이다. 따라서 작은 숫자로 만들어줄 필요가 있다. 상어의 이동 방향이 위, 아래일 경우 이동 가능 거리는 속도를 (R-1) * 2 로 나눈 나머지이고 오른쪽, 왼쪽일 경우 (C-1) * 2 로 나눈 나머지이다. 여기서 R, C는 지도에 row, column 끝 좌표이다.
int dist = map[i][j].speed; // 상어 이동 가능 거리
// 이동 가능 거리 축소
if (map[i][j].dir <= 2) {
dist %= ((R - 1) * 2); // 위 아래
}
else dist %= ((C - 1) * 2); // 오른 왼
int r = i, c = j;
while (dist--) {
int nr = r + dr[map[i][j].dir], nc = c + dc[map[i][j].dir];
if (nr < 1 || nr > R || nc < 1 || nc > C) {
// 벽을 만난 경우 GetReverseDir 함수로 방향 전환
map[i][j].dir = GetReverseDir(map[i][j].dir);
nr = r + dr[map[i][j].dir], nc = c + dc[map[i][j].dir];
}
r = nr, c = nc;
3. 상어가 한 장소에 2마리 이상 존재 할 수 있으므로 map과 크기가 같은 tmp 배열로 이동하고 tmp 배열을 다시 map 배열에 복사해주는 과정이 필요하다. 그리고 상어의 크기가 가장 큰 녀석이 나머지 상어들을 잡아 먹으므로 크기가 가장 큰 상어만 저장하면 된다.
// 만약 이미 상어가 있다면 가장 큰 상어만 저장
if (tmp[r][c].body != 0) {
if (map[i][j].body > tmp[r][c].body)
tmp[r][c] = map[i][j];
}
else tmp[r][c] = map[i][j];
코드
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int R, C, M;
struct INFO {
int speed, dir, body;
};
INFO map[101][101];
const int dr[] = { 0,-1,1,0,0 };
const int dc[] = { 0,0,0,1,-1 };
int Fishing(int pos) {
int ret = 0;
for (int i = 1; i <= R; i++) {
if (map[i][pos].body != 0) {
ret = map[i][pos].body;
map[i][pos] = { 0,0,0 };
break;
}
}
return ret;
}
int GetReverseDir(int idx) {
if (idx == 1) return 2;
if (idx == 2) return 1;
if (idx == 3) return 4;
return 3;
}
void Moving() {
INFO tmp[101][101] = { 0, };
for (int i = 1; i <= R; i++) {
for (int j = 1; j <= C; j++) {
if (map[i][j].body != 0) {
int dist = map[i][j].speed;
if (map[i][j].dir <= 2) {
dist %= ((R - 1) * 2);
}
else dist %= ((C - 1) * 2);
int r = i, c = j;
while (dist--) {
int nr = r + dr[map[i][j].dir], nc = c + dc[map[i][j].dir];
if (nr < 1 || nr > R || nc < 1 || nc > C) {
map[i][j].dir = GetReverseDir(map[i][j].dir);
nr = r + dr[map[i][j].dir], nc = c + dc[map[i][j].dir];
}
r = nr, c = nc;
}
if (tmp[r][c].body != 0) {
if (map[i][j].body > tmp[r][c].body)
tmp[r][c] = map[i][j];
}
else tmp[r][c] = map[i][j];
}
}
}
for (int i = 1; i <= R; i++) {
for (int j = 1; j <= C; j++) {
map[i][j] = tmp[i][j];
}
}
}
int main() {
int ans = 0;
scanf("%d %d %d", &R, &C, &M);
for (int i = 0; i < M; i++) {
int r, c;
scanf("%d %d", &r, &c);
scanf("%d %d %d", &map[r][c].speed, &map[r][c].dir, &map[r][c].body);
}
for (int pos = 1; pos <= C; pos++) {
ans += Fishing(pos);
Moving();
}
printf("%d", ans);
return 0;
}
아쉬운 점
1. 이동 가능한 거리가 1000이하의 숫자라는 점에서 이동 한 위치를 어떻게 바로 구할 수 있을지 생각하는데 오래 걸렸다. 현재 위치에서 다시 제자리로 돌아오기 위해서는 위, 아래의 경우 (R-1)*2, 오른, 왼의 경우 (C-1)*2 칸 만큼 이동했을 때라는 것을 생각해 나머지 연산으로 이동 거리를 축소 시킬 수 있었다. 허나 다른 풀이를 찾아보니 한 번에 다음 위치를 결정할 수 있도록 계산한 풀이들을 볼 수 있었다. 만약 내 방법대로 했을 때도 시간 초과가 나왔을 경우 한 번에 다음 위치를 계산할 수 있는 방법을 생각해내야 한다.
'myt-algorithm-practice > Samsung SW Certi Adv' 카테고리의 다른 글
[Algorithm][C++] BOJ 14503 로봇 청소기 (0) | 2021.09.15 |
---|---|
[Algorithm][C++] BOJ 3190 뱀 (0) | 2021.09.14 |
[Algorithm][C++] BOJ 2234 성곽 (0) | 2021.09.12 |
[Algorithm][C++] BOJ 17144 미세먼지 안녕! (0) | 2021.09.09 |
[Algorithm][C++] BOJ 11048 이동하기 (0) | 2021.09.08 |