티스토리 뷰

문제
https://www.acmicpc.net/problem/17143
17143번: 낚시왕
낚시왕이 상어 낚시를 하는 곳은 크기가 R×C인 격자판으로 나타낼 수 있다. 격자판의 각 칸은 (r, c)로 나타낼 수 있다. r은 행, c는 열이고, (R, C)는 아래 그림에서 가장 오른쪽 아래에 있는 칸이다.
www.acmicpc.net
문제 풀이
단순하게 시간복잡도를 생각해본다면 O(C∗M∗s) = O(109)로 TLE가 남
따라서 상어의 움직임을 줄여야 했고 아래의 관찰을 통해 해결함
-
(상어 H가 같은 위치로 돌아오는데 걸리는 시간) = (오른쪽으로 갔다가 돌아오는 시간) + (왼쪽으로 갔다가 돌아오는 시간)
-
이는 좌표를 우측 90도 방향으로 돌렸을때, (위,아래)로 움직이는 상어들도 동일하게 적용됨
-
따라서 같은 위치로 돌아오는 주기 T=2∗(R−1),T=2∗(C−1) (∵ 양 끝 점은 한 번씩만 방문)
if (di <= 2) v %= (2 * (R - 1)); // (dir <= 2) : left, right else v %= (2 * (C - 1)); // (dir >= 3) : up, down
코드
#include <bits/stdc++.h> using namespace std; const int dir[5][2] = { { 0,0 },{ -1,0 },{ 1,0 },{ 0,1 },{ 0,-1 } }; struct shark { int s, d, z; }; int R, C, M, a, b, c, d, e, grid[101][101], tmp[101][101], ans; shark f[10001]; void moveNeat() { memset(tmp, 0, sizeof(tmp)); int v, sz, di, nr, nc; for (int i = 1; i <= R; i++) { for (int j = 1; j <= C; j++) { if (grid[i][j]) { v = f[grid[i][j]].s, di = f[grid[i][j]].d, sz = f[grid[i][j]].z; nr = i, nc = j; if (di <= 2) v %= (2 * (R - 1)); else v %= (2 * (C - 1)); while (v--) { if ((nr == 1 && di == 1) || (nr == R && di == 2)) di = 3 - di; else if ((nc == 1 && di == 4) || (nc == C && di == 3)) di = 7 - di; nr += dir[di][0], nc += dir[di][1]; } f[grid[i][j]].d = di; if (!tmp[nr][nc]) tmp[nr][nc] = grid[i][j]; else if (f[tmp[nr][nc]].z < f[grid[i][j]].z) tmp[nr][nc] = grid[i][j]; } } } for (int i = 1; i <= R; i++) for (int j = 1; j <= C; j++) grid[i][j] = tmp[i][j]; } void fishing(int pos) { for (int i = 1; i <= R; i++) { if (grid[i][pos]) { ans += f[grid[i][pos]].z; grid[i][pos] = 0; break; } } } int main() { cin.tie(NULL); cout.tie(NULL); ios_base::sync_with_stdio(false); cin >> R >> C >> M; for (int i = 1; i <= M; i++) { cin >> a >> b >> c >> d >> e; f[i] = { c,d,e }; grid[a][b] = i; } for (int t = 1; t <= C; t++) { fishing(t); moveNeat(); } cout << ans; }
어떻게 구현 ?
위의 생각까지 마쳤다면 두 함수를 구현할 수 있음
1. 상어를 잡는 함수
void fishing(int pos) { for (int i = 1; i <= R; i++) { if (grid[i][pos]) { ans += f[grid[i][pos]].z; grid[i][pos] = 0; break; } } }
2. 상어의 움직임을 제어하는 함수
memset(tmp, 0, sizeof(tmp));
⑴ 이동할 좌표에 상어정보 초기화
if ((nr == 1 && di == 1) || (nr == R && di == 2)) di = 3 - di; else if ((nc == 1 && di == 4) || (nc == C && di == 3)) di = 7 - di;
⑵ 격자판의 끝 점에서 상어의 방향이 격자판 바깥을 향한다면 반대방향으로 돌려줌
f[grid[i][j]].d = di;
⑶ 이동이 끝난 후 해당 상어의 방향을 교체해줌
/* tmp[nr][nc] : 이동할 좌표의 상어인덱스 f[grid[i][j]] : 이동전 좌표의 상어인덱스*/ if (!tmp[nr][nc]) tmp[nr][nc] = grid[i][j]; else if (f[tmp[nr][nc]].z < f[grid[i][j]].z) tmp[nr][nc] = grid[i][j];
⑷ 이동한 좌표에 상어가 없다면 상어의 인덱스를 저장하고, 상어가 존재한다면 크기를 비교하여 크기가 더 큰 상어의 인덱스를 저장
for (int i = 1; i <= R; i++) for (int j = 1; j <= C; j++) grid[i][j] = tmp[i][j];
⑸ 이동한 좌표의 상어정보를 현 좌표에 갱신
'Algorithm > BOJ' 카테고리의 다른 글
[백준 19576] 약수 (0) | 2020.08.31 |
---|---|
[백준 19588] 상품권 준비 (0) | 2020.08.31 |
[백준 19591] 독특한 계산기 (0) | 2020.08.31 |
[백준 1662] 압축 (0) | 2020.08.31 |
[백준 17080] 결함게임 (0) | 2020.08.27 |
- Total
- Today
- Yesterday
- 표 편집
- 2022 카카오 블라인드 코딩테스트
- 구현
- 프로그래머스 월간코드챌린지
- 시뮬레이션
- 이분탐색
- BFS
- 유니온파인드
- 2022 카카오블라인드
- DP
- 카카오 2차코딩테스트
- 프로그래머스
- 투포인터
- 2020 KAKAO BLIND RECRUITMENT
- 2022 KAKAO BLIND RECRUITMENT
- 누적합
- 위클리 챌린지
- 파싱
- 백준
- 2021 카카오 블라인드
- 프로그래머스 위클리 9주차
- 게임이론
- 트리
- 동적계획법
- 카카오 인턴십
- 카카오 표 편집
- 카카오 2021
- 카카오 2020 인턴십
- 2021 KAKAO BLIND
- Kakaoblind
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |