[문제보기]
17143. 낚시왕
17143번: 낚시왕
낚시왕이 상어 낚시를 하는 곳은 크기가 R×C인 격자판으로 나타낼 수 있다. 격자판의 각 칸은 (r, c)로 나타낼 수 있다. r은 행, c는 열이고, (R, C)는 아래 그림에서 가장 오른쪽 아래에 있는 칸이다.
www.acmicpc.net
[풀이과정]
상어에 대한 정보를 저장하기 위해 {상어.좌표y, x, 속력, 방향, 크기, 생존유무}를 담고있는 구조체를 만들었다.
그리고 vector<int> map함수를 만들었는데, 배열 형식으로 미리 크기를 정해주었다. vector로 만들어준 이유는
상어를 이동 후 한 칸에 여러마리 상어가 있을 경우를 알기 위해 vector로 만들어주었다.
전체 코드 형식은
1. 낚시
2. 상어 이동
3. 상어 죽이기
로 3단계로 나누어서 작동을 한다.
1. 낚시 / Catch_Fisher(int Cur) 함수
현재 낚시꾼의 위치를 Cur변수로 보내준다. 그리고 행에 대해서 확인을 통해 제일 위에 있는(낚시꾼과 가까이 있는)
상어를 잡는다. 잡았다라는 표시는 상어를 죽이는 걸로 대체했다.(Shark[].live = false)
2. 상어 이동 / Move_Shark() 함수
맨 처음 map에 대해 clear()를 해준다. 모든 상어 비워주기
그리고 Shark[]에 담겨있는 정보를 가지고 상어를 이동해 주는데, 이 때 최악의 경우 속력이 100이고, 상어가 10000마리가 있을 때, 10^7이 되고, 낚시꾼이 움직이는 경우 100까지 해주면 연산은 10^9가 형성이 되어 1초가 넘게된다.
그렇기 때문에 속력에 대한 숫자를 줄어줘야하는데
예를 들어 방향이 1 or 2인 상어에 대해 자기 자리로 오는 수는 ((R-1)*2) 라는 규칙이 만들어지는데,
R = 3일 때, 1 = 5,
R = 4일 때, 1 = 7,
R = 5일 때, 1 = 9와 같아진다.
이렇게 속력에 대한 숫자를 줄어준 뒤 상어를 이동시켜준다. 이동 시킬 때, map밖으로 나가게 되면 Inverse_Dir() 함수를
이용하여 방향을 반대로 바꿔준다.
3. 상어죽이기 / Kill_Shark() 함수
Kill_Shark() 함수를 이용하여 상어를 죽이게 되는데, map[][]를 검사를 하여 사이즈가 2이상이 되는 곳에 대해서
상어 크기에 맞게 정렬을 한 후 한 마리 빼고 모두 죽이면 된다.
[소스코드]
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef struct _SHARK{
int y;
int x;
int speed;
int dir;
int size;
bool live;
} SHARK;
int R, C, M, ans = 0;
vector<int> map[101][101];
SHARK Shark[10000];
pair<int,int> movdir[5] = {{0,0}, {-1, 0}, {1, 0}, {0, 1}, {0, -1}};
bool cmp(int a, int b){
return Shark[a].size > Shark[b].size;
}
int Inverse_Dir(int dir){
if(dir == 1) return 2;
else if(dir == 2) return 1;
else if(dir == 3) return 4;
return 3;
}
void Catch_Fisher(int Cur){
for(int i = 1; i<=R; i++){
if(!map[i][Cur].empty()){
int Shark_num = map[i][Cur][0];
ans += Shark[Shark_num].size;
Shark[Shark_num].live = false;
return;
}
}
}
void Move_Shark(){
for(int i=1; i<=R; i++){
for(int j=1; j<=C; j++){
map[i][j].clear();
}
}
for(int i=0; i<M; i++){
if(Shark[i].live == false) continue;
int y = Shark[i].y;
int x = Shark[i].x;
int dir = Shark[i].dir;
int speed = Shark[i].speed;
if(dir == 1 || dir == 2){
speed = speed %((R-1)*2);
}
else{
speed = speed %((C-1)*2);
}
int ny = y, nx = x;
while(1){
if(speed == 0) break;
ny = y + movdir[dir].first;
nx = x + movdir[dir].second;
if(0 < ny && ny <= R && 0 < nx && nx <= C){
y = ny;
x = nx;
speed--;
}
else{
dir = Inverse_Dir(dir);
}
}
Shark[i].y = ny;
Shark[i].x = nx;
Shark[i].dir = dir;
map[ny][nx].push_back(i);
}
}
void Kill_Shark(){
for(int i=1; i<= R; i++){
for(int j=1; j<=C; j++){
if(map[i][j].size() >= 2){
sort(map[i][j].begin(), map[i][j].end(), cmp);
for(int k=1; k<map[i][j].size(); k++){
int idx = map[i][j][k];
Shark[idx].live = false;
}
}
}
}
}
int main(){
cin >> R >> C >> M;
if(M == 0){
cout << 0;
return 0;
}
for(int i=0; i<M; i++){
cin >> Shark[i].y >> Shark[i].x >> Shark[i].speed >> Shark[i].dir >> Shark[i].size;
Shark[i].live = true;
map[Shark[i].y][Shark[i].x].push_back(i);
}
for(int i=1; i<=C; i++){
Catch_Fisher(i);
if(i == C) break;
Move_Shark();
Kill_Shark();
}
cout << ans;
}
[해결 과정 중 실수한 부분]
코드를 확실하게 다 짰지만, 시간 초과가 나와 시간을 줄이는 부분을 생각해봤는데, 속력에 대해 숫자를 줄일 수 있다는
것을 찾고 이 부분을 고치니 통과가 되었다.
'알고리즘 스터디 > Beakjoon' 카테고리의 다른 글
| [백준 13460][C++] 구슬 탈출 2 (Gold 2) (0) | 2020.09.20 |
|---|---|
| [백준 17837][C++] 새로운 게임2 (Gold 2) (0) | 2020.09.18 |
| [백준 1920][C++] 수 찾기 (Silver 4) (0) | 2020.09.12 |
| [백준 1463][C++] 1로 만들기 (Silver 3) (0) | 2020.09.12 |
| [백준 11052][C++] 카드 구매하기 (Silver 1) (0) | 2020.09.09 |