컴퓨터 공학 기초/알고리즘 (구현)
백준 17143 (낚시왕)
JongSeok_12
2020. 7. 27. 21:04
https://www.acmicpc.net/problem/17143
17143번: 낚시왕
낚시왕이 상어 낚시를 하는 곳은 크기가 R×C인 격자판으로 나타낼 수 있다. 격자판의 각 칸은 (r, c)로 나타낼 수 있다. r은 행, c는 열이고, (R, C)는 아래 그림에서 가장 오른쪽 아래에 있는 칸이다.
www.acmicpc.net
간단한 구현 문제이다.
상어의 위치가 주어지며 격자판 안에 상어가 존재한다. 낚시꾼은 X축을 +1 하며 이동하면서 마지막 X축 까지 이동하면서 잡은 상어의 총크기를 구하면 되는 문제이다.
이때 주의해야 할 점이 있는데 상어가 이동할 수 있는 경우가 최대 1000 번이기 때문에 시간 초과를 주의해야 한다.
TIP :
상어가 격자판의 Y or X 축을 한바퀴 돌아 제자리로 돌아오는 경우 몇 번 이동하는지 구하여 상어가 이동하는 횟수와 나누어 나머지 값을 취하면 다음과 같은 식이 성립한다.
(상어가 한바퀴를 돌아 제자리로 돌아오기까지 걸리는 횟수) / (상어가 움직여야 하는 횟수)를 수행하여
만약 몫이 1 이상이라면 해당 상어는 몫에 해당하는 횟수만큼 본래의 자리를 들렷다 이동하기 때문에 몫에 해당하는 횟수의 연산을 없애고 나머지에 해당하는 횟수만큼 상어를 이동시키면 된다.
만약 몫이 1 보다 작다면 해당 상어는 한바퀴보다 덜 돌기 때문에 그냥 상어에게 주어진 회전 횟수만큼 연산을 수행하면 된다.
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
int check[4][2] = {
-1, 0,
+1, 0,
0, +1,
0, -1
};
struct Node{
int y, x;
int speed;
int dir;
int body;
int name;
int life;
};
vector<Node> sList;
int map[100][100];
int my, mx, m;
void move(){
int n = sList.size();
int overlap[100][100] = {0};
for (int i = 0; i < n; ++i){
Node now = sList[i];
if (now.life == 1) continue;
int sp;
if (now.dir == 0 || now.dir == 1) sp = 2 * (my - 1);
else if (now.dir == 2 || now.dir == 3)sp = 2 * (mx - 1);
// 상어가 한바퀴 회전하여 제자리까지 돌아올 경우
if (sp <= now.speed) sp = now.speed % sp;
// 상어가 한바퀴 미만으로 이동할 경우
else sp = now.speed;
for (int j = 0; j < sp; ++j){
int dy = now.y + check[now.dir][0];
int dx = now.x + check[now.dir][1];
if (dy >= 0 && dx >= 0 && dy < my && dx < mx){
now.y = dy;
now.x = dx;
}
else{
if (now.dir == 0) now.dir = 1;
else if (now.dir == 1) now.dir = 0;
else if (now.dir == 2) now.dir = 3;
else if (now.dir == 3) now.dir = 2;
now.y = now.y + check[now.dir][0];
now.x = now.x + check[now.dir][1];
}
}
sList[i] = now;
// 상어가 이동한 위치에 아무도 없을 경우
if (overlap[now.y][now.x] == 0){
overlap[now.y][now.x] = now.name;
}
// 상어가 이동한 위치에 누군가 있을경우 상어의 크기를 비교하여 선택
// 없앨 상어는 life 에 check
else{
if (sList[overlap[now.y][now.x] - 1].body < now.body){
sList[overlap[now.y][now.x] - 1].life = 1;
overlap[now.y][now.x] = now.name;
}
else{
sList[i].life = 1;
}
}
}
memcpy(map, overlap, 4 * 100 * 100);
}
int main(){
freopen_s(new FILE*, "tes.text", "r", stdin);
cin >> my >> mx >> m;
int result = 0;
int dy, dx, dir;
Node tmp;
for (int i = 0; i < m; ++i){
cin >> dy >> dx >> tmp.speed >> dir >> tmp.body;
tmp.y = dy - 1;
tmp.x = dx - 1;
tmp.dir = dir - 1;
tmp.name = i + 1;
map[dy - 1][dx - 1] = i + 1;
sList.push_back(tmp);
}
for (int x = 0; x < mx; ++x){
for (int y = 0; y < my; ++y){
// 해당 X축의 가장가까운 상어 삭제
if (map[y][x] > 0){
sList[map[y][x] - 1].life = 1;
result += sList[map[y][x] - 1].body;
break;
}
}
move();
}
printf("%d", result);
}