알고리즘 모음(C++)

백준 17143 - 낚시왕(C++) 본문

백준

백준 17143 - 낚시왕(C++)

공대생의 잡다한 사전 2021. 8. 15. 00:01

문제 링크입니다 https://www.acmicpc.net/problem/17143

 

17143번: 낚시왕

낚시왕이 상어 낚시를 하는 곳은 크기가 R×C인 격자판으로 나타낼 수 있다. 격자판의 각 칸은 (r, c)로 나타낼 수 있다. r은 행, c는 열이고, (R, C)는 아래 그림에서 가장 오른쪽 아래에 있는 칸이다.

www.acmicpc.net

삼성 SW 역량 테스트 기출문제였습니다!

문제 조건

 

출력 예시

 

문제 접근 방법

1. 상어의 정보를 vector에 저장한다.

2. 먼저 낚시꾼이 상어를 잡는다. -> 이때 잡은 상어는 잡았다는 표시를 한다.

3. 상어를 움직인다. -> 이때 speed만큼 전부 움직인다면 시간초과가 된다. 따라서 움직이는 횟수를 줄여야한다.

                          -> 한마리 상어를 전부 움직였을때, 그 자리에 상어가 있다면 크기를 비교해 상어를 없앤다.

4. 2번과 3번을 C만큼 반복한다.

 

문제 접근 방법 3-1번 움직임에 대한 부가 설명

최악의 경우에 상어가 10000마리, 상어의 speed가 전부 1000이라고 할때, 한번 상어가 전부 움직일 때마다 10^8의 연산이 필요합니다. 이때 무조건 시간 초과가 됩니다. 따라서 움직임을 줄이는 방법이 필요합니다.

(1,1) (1,2) (1,3) (1,4) (1,5) (1,6) (1,7)
(2,1) (2,2) (2,3) (2,4) (2,5) (2,6) (2,7)
(3,1) (3,2) (3,3) (3,4) (3,5) (3,6) (3,7)

위와 같은 좌표가 있다고 했을 때,

(2,5)에서 9번 오른쪽으로 움직이면 어떻게 될까? -> (2,2)로 도착한다.

(2,5)에서 4번 오른쪽으로 움직였을때는? -> (2,5)로 돌아온다.

(2,5)에서 12번 오른쪽으로 움직였을때는? -> (2,5)로 돌아온다.

따라서 R 또는 C범위 만큼 움직일 때, (R-1)*2 또는 (C-1)*2의 나머지 만큼만 움직이면 전체를 움직인 것과 같은 효과를 볼 수 있다!

 

 

문제 접근 방법 - 2번

void capture_shark(int y) {
	for (int i = 1; i <= R; i++) {
		if (num_shark[i][y] > 0) {
			get_shark += shark[num_shark[i][y]-1].size_;
			out_shark[num_shark[i][y]-1] = true;
			break;
		}
	}
}

해당 열 번호에서 1~R까지 행을 살펴봅니다. 위에서부터 봤을 때, 해당 좌표에 상어가 있다면 상어를 잡은 후에 그 상어를 잡았다는 표시를 합니다.

num_shark[][] -> 해당 좌표에 X번 상어가 존재한다

out_shark[] -> 해당 번호의 상어가 잡혔는지의 여부를 알려준다. -> 계속 나오니깐 기억해주세요

 

 

문제 접근 방법 - 3번

void move(int num, int x, int y, int speed, int dir) {
	if (dir == 1 || dir == 2) {
		int rotate = (R - 1) * 2;
		if (speed >= rotate) speed = speed % rotate;
	}
	else {
		int rotate = (C - 1) * 2;
		if (speed >= rotate) speed = speed % rotate;
	}
	while (1) {
		if (speed == 0) break;
		if (dir == 1) {
			if (x == 1) dir = 2;
		}
		else if (dir == 2) {
			if (x == R) dir = 1;
		}
		else if (dir == 3) {
			if (y == C) dir = 4;
		}
		else if (dir == 4) {
			if (y == 1) dir = 3;
		}
		x += dx[dir-1];
		y += dy[dir-1];
		speed--;
	}
	shark[num].r = x;
	shark[num].c = y;
	shark[num].dir = dir;
	if (num_shark[x][y] != 0) {
		if (shark[num_shark[x][y] - 1].size_ < shark[num].size_) {
			out_shark[num_shark[x][y] - 1] = true;
			num_shark[x][y] = num + 1;
		}
		else {
			out_shark[num] = true;
		}
	}
	else {
		num_shark[x][y] = num + 1;
	}
}

void move_shark() {
	for (int i = 0; i < M; i++) {
		if (!out_shark[i]) {
			int x = shark[i].r;
			int y = shark[i].c;
			int speed = shark[i].speed;
			int direction = shark[i].dir;
			int size_ = shark[i].size_;
			move(i,x, y, speed, direction);
		}
	}
}

해당 번호의 상어가 존재할 때, 백터에 담아둔 정보를 통해서 상어를 움직입니다.

1. 위, 아래로 움직일 때 -> (R-1)*2의 나머지 만큼만 움직입니다.

2. 왼, 오른쪽으로 움직일 때 -> (C-1)*2의 나머지 만큼만 움직입니다.

상어가 도착한 좌표에 이전에 도착했던 상어가 존재한다면 -> 크기를 비교해 큰 상어만 남깁니다!

 

자세한 것은 코드를 참고해주세요!

 

#define CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>
#include <cstring>
#include <cmath>
#define MAX 100001
using namespace std;

int R, C, M;
int map[101][101];
int dx[4] = { -1,1,0,0 };
int dy[4] = { 0,0,1,-1 };
int get_shark;
typedef struct sh {
	int r;
	int c;
	int speed;
	int dir;
	int size_;
}sh;
bool out_shark[10001];
vector<sh> shark;
int num_shark[101][101];

void capture_shark(int y) {
	for (int i = 1; i <= R; i++) {
		if (num_shark[i][y] > 0) {
			get_shark += shark[num_shark[i][y]-1].size_;
			//cout << num_shark[i][y] << " ";
			out_shark[num_shark[i][y]-1] = true;
			break;
		}
	}
}


void move(int num, int x, int y, int speed, int dir) {
	if (dir == 1 || dir == 2) {
		int rotate = (R - 1) * 2;
		if (speed >= rotate) speed = speed % rotate;
	}
	else {
		int rotate = (C - 1) * 2;
		if (speed >= rotate) speed = speed % rotate;
	}
	while (1) {
		if (speed == 0) break;
		if (dir == 1) {
			if (x == 1) dir = 2;
		}
		else if (dir == 2) {
			if (x == R) dir = 1;
		}
		else if (dir == 3) {
			if (y == C) dir = 4;
		}
		else if (dir == 4) {
			if (y == 1) dir = 3;
		}
		x += dx[dir-1];
		y += dy[dir-1];
		speed--;
	}
	//cout << x << " " << y << " " << " " << num + 1 << "\n";
	shark[num].r = x;
	shark[num].c = y;
	shark[num].dir = dir;
	if (num_shark[x][y] != 0) {
		if (shark[num_shark[x][y] - 1].size_ < shark[num].size_) {
			out_shark[num_shark[x][y] - 1] = true;
			num_shark[x][y] = num + 1;
		}
		else {
			out_shark[num] = true;
		}
	}
	else {
		num_shark[x][y] = num + 1;
	}
}

void move_shark() {
	for (int i = 0; i < M; i++) {
		if (!out_shark[i]) {
			int x = shark[i].r;
			int y = shark[i].c;
			int speed = shark[i].speed;
			int direction = shark[i].dir;
			int size_ = shark[i].size_;
			move(i,x, y, speed, direction);
		}
	}
}

void solve() {
	for (int i = 1; i <= C; i++) {
		capture_shark(i);
		memset(num_shark, 0, sizeof(num_shark));
		move_shark();
	}
	cout << get_shark;
}

int main() {
	cin.tie(0);
	cout.tie(0);
	cin >> R >> C >> M;
	for (int i = 1; i <= M; i++) {
		int r, c, s, d, z;
		cin >> r >> c >> s >> d >> z;
		shark.push_back({ r,c,s,d,z });
		num_shark[r][c] = i;
	}
	solve();
	return 0;
}

 

 

질문 및 조언 댓글 남겨주세요!

'백준' 카테고리의 다른 글

백준 13418 - 학교 탐방하기(C++)  (0) 2021.08.16
백준 14950 - 정복자(C++)  (0) 2021.08.16
백준 1103 - 게임(C++, 복습)  (0) 2021.08.14
백준 14442 - 벽 부수고 이동하기 2(C++)  (0) 2021.08.10
백준 -6593 - 상범 빌딩(C++)  (0) 2021.08.10