Study hard
(c++)백준 17143번: 낚시왕 본문
17143번: 낚시왕
낚시왕이 상어 낚시를 하는 곳은 크기가 R×C인 격자판으로 나타낼 수 있다. 격자판의 각 칸은 (r, c)로 나타낼 수 있다. r은 행, c는 열이고, (R, C)는 아래 그림에서 가장 오른쪽 아래에 있는 칸이다.
www.acmicpc.net




[풀이]
문제에 나온 규칙대로 구현하는 문제였다.
처음에 모든 상어를 각각의 s만큼 움직이게 해서 위치를 갱신해주었는데, 시간초과가 났다.
최악의 경우 10^3(상어 속력)*10^4(상어의 수)*10^2(C의 크기) = 10^9번의 연산을 하게 되므로 시간초과가 나게 된다!
상어가 위 아래로 움직일 땐 (R-1)*2, 좌우로 움직일 땐 (C-1)*2번 움직이면 같은 자리에 같은 방향을 가지고 돌아오게 된다.
이걸 이용하여 실제 움직이는 칸 수를 s%((R-1)*2)또는 s%((C-1)*2)로 하여 풀면 시간초과가 나지 않는다.
그리고 상어를 이동시킬 때 여러마리 상어의 위치가 섞이게 되므로 이미 움직인 상어를 표시하는 move 변수를 Shark구조체에 포함시켜야 했다.
※시간복잡도 계산 연습이 필요할 듯
#include <iostream>
#include <deque>
#include <algorithm>//sort
using namespace std;
struct Shark {
int s, d, z;//속력,방향,크기
int move;//움직였는지
};
bool sortShark(Shark &A, Shark &B) {
return A.z > B.z;
}
int R, C, M;
deque<Shark>shark[101][101];//각 칸의 상어들 상태 저장
bool check[101][101];//상어가 있는 칸 체크
const int dx[] = { 0,-1,1,0,0 };//1:위, 2:아래
const int dy[] = { 0,0,0,1,-1 };//3:오른쪽, 4:왼쪽
int convert[] = { 0,2,1,4,3 };//방향 바뀔때 사용
int sum = 0;
int moveLabel = -1;
void Move(int x, int y, int s, int d, int z) {
if (s == 0) {
shark[x][y][0].move = -moveLabel;
return;
}
int realMove = 0;
if (d == 1 || d == 2) {
//제자리에 같은 방향으로 돌아오는 경우 빼주기
realMove = s % ((R - 1) * 2);
}
else
realMove = s % ((C - 1) * 2);
int nx = x;
int ny = y;
int nd = d;
while (realMove--) {
nx += dx[nd];
ny += dy[nd];
//경계 넘어가면 방향 전환
if (nx <= 0 || nx > R || ny <= 0 || ny > C) {
nx -= dx[nd];
ny -= dy[nd];
nd = convert[nd];
nx += dx[nd];
ny += dy[nd];
}
}
shark[x][y].pop_front();
shark[nx][ny].push_back({ s,nd,z,-moveLabel });
}
//상어이동
void moveShark() {
//칸에 상어 있으면 이동
for (int i = 1; i <= R; i++) {
for (int j = 1; j <= C; j++) {
if (shark[i][j].empty())
continue;
if (shark[i][j][0].move == -moveLabel)
continue;
int s = shark[i][j][0].s;
int d = shark[i][j][0].d;
int z = shark[i][j][0].z;
Move(i, j, s, d, z);
}
}
}
//상어 잡아먹기
void eatShark() {
//상어가 두마리 있으면 큰 상어가 잡아먹기
for (int i = 1; i <= R; i++) {
for (int j = 1; j <= C; j++) {
int sharkcnt = shark[i][j].size();
if (sharkcnt > 1) {
sort(shark[i][j].begin(), shark[i][j].end(), sortShark);
shark[i][j].erase(shark[i][j].begin() + 1, shark[i][j].end());
}
}
}
}
void getShark() {
//한 칸씩 이동하면서 상어잡기
for (int col = 1; col <= C; col++) {
for (int row = 1; row <= R; row++) {
int sharkcnt = shark[row][col].size();
//제일 가까운 상어 찾았으면
if (sharkcnt > 0) {
//cout << "r: " << row << ' ' << "c: " << col << '\n';
//cout<< shark[row][col][0].z << '\n';
sum += shark[row][col][0].z;
shark[row][col].pop_back();
break;
}
}
moveShark();
eatShark();
moveLabel = -moveLabel;
}
}
void solution() {
cin >> R >> C >> M;
for (int i = 0; i < M; i++) {
int r, c, s, d, z;
cin >> r >> c >> s >> d >> z;
shark[r][c].push_back({ s,d,z,moveLabel });
}
getShark();
cout << sum << '\n';
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
solution();
return 0;
}
'백준 > 시뮬레이션,구현' 카테고리의 다른 글
(c++)백준 17822번: 원판 돌리기 (0) | 2021.03.04 |
---|---|
(c++)백준 17140번: 이차원 배열과 연산 (0) | 2020.10.17 |
(c++)백준 16235번: 나무 재테크 (0) | 2020.10.16 |
(c++)백준 5373번: 큐빙 (0) | 2020.10.15 |
(c++)백준 3190번: 뱀 (0) | 2020.10.15 |