[백준 18111] 마인크래프트(C++)

2022. 9. 13. 17:01· CodingTest/Baekjoon
목차
  1. 🔎문제 해석
  2. 📃코드
  3. ✔ 느낀 점

📕문제


팀 레드시프트는 대회 준비를 하다가 지루해져서 샌드박스 게임인 ‘마인크래프트’를 켰다. 마인크래프트는 1 × 1 × 1(세로, 가로, 높이) 크기의 블록들로 이루어진 3차원 세계에서 자유롭게 땅을 파거나 집을 지을 수 있는 게임이다.

목재를 충분히 모은 lvalue는 집을 짓기로 하였다. 하지만 고르지 않은 땅에는 집을 지을 수 없기 때문에 땅의 높이를 모두 동일하게 만드는 ‘땅 고르기’ 작업을 해야 한다.

lvalue는 세로 N, 가로 M 크기의 집터를 골랐다. 집터 맨 왼쪽 위의 좌표는 (0, 0)이다. 우리의 목적은 이 집터 내의 땅의 높이를 일정하게 바꾸는 것이다. 우리는 다음과 같은 두 종류의 작업을 할 수 있다.

  1. 좌표 (i, j)의 가장 위에 있는 블록을 제거하여 인벤토리에 넣는다.
  2. 인벤토리에서 블록 하나를 꺼내어 좌표 (i, j)의 가장 위에 있는 블록 위에 놓는다.

1번 작업은 2초가 걸리며, 2번 작업은 1초가 걸린다. 밤에는 무서운 몬스터들이 나오기 때문에 최대한 빨리 땅 고르기 작업을 마쳐야 한다. ‘땅 고르기’ 작업에 걸리는 최소 시간과 그 경우 땅의 높이를 출력하시오.

단, 집터 아래에 동굴 등 빈 공간은 존재하지 않으며, 집터 바깥에서 블록을 가져올 수 없다. 또한, 작업을 시작할 때 인벤토리에는 B개의 블록이 들어 있다. 땅의 높이는 256블록을 초과할 수 없으며, 음수가 될 수 없다.

📕입력


첫째 줄에 N, M, B가 주어진다. (1 ≤ M, N ≤ 500, 0 ≤ B ≤ 6.4 × 107)

둘째 줄부터 N개의 줄에 각각 M개의 정수로 땅의 높이가 주어진다. (i + 2) 번째 줄의 (j + 1) 번째 수는 좌표 (i, j)에서의 땅의 높이를 나타낸다. 땅의 높이는 256보다 작거나 같은 자연수 또는 0이다.

📕출력


첫째 줄에 땅을 고르는 데 걸리는 시간과 땅의 높이를 출력하시오. 답이 여러 개 있다면 그중에서 땅의 높이가 가장 높은 것을 출력하시오.

🔎문제 해석


문제를 풀기 전에는 항상 어떻게 하면 깔끔하게 풀 수 있을까를 굉장히 고민을 많이 한다.

고민의 결과는 땅의 높이는 최대 256이기에 모든 경우의 수를 구해도 시간초과가 나지 않을 것 같아서 브루트 포스 알고리즘(약칭 : 막일)을 사용하기로 했다.

n * m 행렬에 대해서 0~256까지의 높이에 대해서 검사를 했다.

우선 해당 지점에서 검사하고자 하는 높이와의 차이를 변수 num에 저장했다.

 

💡num값은 3가지로 분류될것이다.

  • 양수 : 해당 지점과의 차이가 양수라는 뜻은 쌓여있는 블록의 개수를 제거해서 인벤토리에 넣는다.
  • 음수 : 해당 지점과의 차이가 음수라는 뜻은  인벤토리에 있는 블록을 꺼내서 땅에 쌓아야 한다.
  • 0 : 해당 지점과의 차이가 0은 인벤토리에 들어있는 블록 개수의 변화가 없다.

💡인벤토리에서 꺼내는 블록의 수가 (인벤토리에 넣은 블록의 수 + 기존 인벤토리에 있는 블록의 수) 보다 적어야 한다.

만약 크다면 해당 높이에 대해서는 작업이 이루어질 수 없다!

그 후에 인벤토리에서 꺼낼 때의 작업이 1초가 걸리고, 인벤토리에서 넣을 때의 작업이 2초가 걸리기에 해당 시간을 t에 저장하고 그때의 높이를 저장하고 출력했다.

📃코드


/*
백준 실버2 마인크래프트
*/
#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>
using namespace std;
int n, m, b,height, bigT = INT_MAX;
vector<vector<int>> graph;
int main()
{
cin >> n >> m >> b;
graph.resize(n, vector<int>(m, 0));
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
cin >> graph[i][j];
}
}
for (int k = 0; k < 257; k++) //모든 높이에 대해서 검사함.
{
int addblock = 0; //높이가 모자랄때 쌓는 블록의 개수를 저장함.
int subblock = 0; //높이가 남을때 제거하는 블록의 개수를 저장함.
int t = 0; //현재 높이에 대해서 검사할 때 시간을 저장함.
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
int num = graph[i][j] - k; //해당 지점에서 높이와의 차이를 저장. -> 필요하거나 남는 블록 수
if (num < 0) { //차이가 음수라면 그 차이만큼 땅의 높이를 올리고 addblock을 증가시킴. 시간 : 1초
addblock += num; //올릴때 쓰이는 블록 수
}
else if (num > 0) { //치이가 양수라면 그 차이만큼 땅의 높이를 내리고 subblock을 증가시킴. 시간 : 2초
subblock += num; //내릴떄 쓰이는 블록 수
}
}
}
if (addblock*-1 > b+subblock) { //내가 더해주고 빼준 블록의 수의 합이 내가 들고있는 블록의 수보다 많다면 이것은 잘못된 것.
continue;
}
else { //subblock-addblock>=b
t = addblock*-1 + subblock * 2;
if (t <= bigT) {
bigT = t;
height = k;
}
}
//높이 k에 대해서 모든 addblock과 subblock을 수집햇고.
//만약 높이가 갚을 경우는 ? 시간이 영초겟죠
/*
int num = graph[i][j];
while (num != k)
{
if (num > k) //높을때는 높이 -1 현재블록수 + 1 --> 시간 2초걸림
{
num -= 1;
nowblock += 1;
t += 2;
}
else //낮을때는 높이 +1 블록 -1 --> 시간 1초걸림
{
num += 1;
nowblock -= 1;
t += 1;
}
if (nowblock < 0)
{ //블록의 개수가 0보다 작아진다면 해당 높이를 맞출수는없음.
flag=false;
}
if(flag==false){
break;
}
}
--> 시간 초과 코드 */
}
cout << bigT << " " << height << endl;
}

✔ 느낀 점

  • 처음 작성한 코드에서는 시간 초과가 발생했다. 
    • 해당 지점과의 높이 차이에 대해서 while문을 돌렸기 때문이다. (사실 엄청 불필요한 작업이었다. 해당 차이만큼 연산을 곱해주면 되는 것인데...)
  • 지금 작성한 코드와 기존 코드와의 알고리즘적으로 큰 차이는 없다!.
저작자표시 (새창열림)

'CodingTest > Baekjoon' 카테고리의 다른 글

[백준 20057] 마법사 상어와 토네이도(C++)  (0) 2022.09.15
[백준 14500] 테트로미노(C++)  (0) 2022.09.14
[백준 2281] 데스노트(C++)  (0) 2022.09.08
[백준 2156] 포도주 시식(C++)  (0) 2022.09.06
[백준 1309] 동물원(C++)  (0) 2022.09.04
  1. 🔎문제 해석
  2. 📃코드
  3. ✔ 느낀 점
'CodingTest/Baekjoon' 카테고리의 다른 글
  • [백준 20057] 마법사 상어와 토네이도(C++)
  • [백준 14500] 테트로미노(C++)
  • [백준 2281] 데스노트(C++)
  • [백준 2156] 포도주 시식(C++)
재한
재한
안녕하세요 💻
재한
짜이한
전체
오늘
어제
  • 분류 전체보기 (502)
    • Skils (116)
      • Android (50)
      • C++ (5)
      • Kotlin (36)
      • Algorithm (24)
      • Server (1)
    • CodingTest (228)
      • Programmers (45)
      • Baekjoon (183)
    • Experience (8)
      • 후기(코딩테스트,프로그램,프로젝트) (8)
    • Computer Science (70)
      • Design Pattern (2)
      • OOP (2)
      • Computer Architecture (14)
      • OS (2)
      • Software Engineering (3)
      • DataBase (8)
      • Network (39)
    • 학교 (75)
      • R프로그래밍 (26)
      • 회계와 사회생활 (17)
      • 컴퓨터학개론 (20)
      • it기술경영개론 (12)

블로그 메뉴

  • 홈
  • 태그
  • 카테고리
  • 글쓰기
  • 설정

인기 글

최근 댓글

최근 글

hELLO · Designed By 정상우.v4.2.2
재한
[백준 18111] 마인크래프트(C++)
상단으로

티스토리툴바

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.