https://www.acmicpc.net/problem/23288
[필자 사고]
구현 문제이다. 구현 문제에서 가장 중요한 습관 중 하나는 한번에 모든 코드를 쏟아 붇는게 아닌
조각 조각 객체 지향적으로 함수를 만들어 하나하나 작은부붙부터 조립해야 된다는 점이다.
문제에서 주요 포인트는 Dice를 굴리는 상황을 어떻게 코드를 만들지와
주사위 맵에서 자신과 동일한 점수를 어떻게 찾을지가 관건인 문제이다.
아래는 필자가 작성한 코드들의 설명이다.
1. 초기화 (initDice 함수)
주사위의 초기 상태를 설정합니다. 주사위는 6개의 면을 가지며, 각 면의 초기 값은 다음과 같습니다:
- 0: 밑면
- 1: 윗면
- 2: 왼쪽
- 3: 오른쪽
- 4: 앞면
- 5: 뒷면
void initDice() {
Dice.resize(6);
for (int i = 0; i <6; i++) {
Dice[i] = i;
}
//0 밑 1 위 2 왼 3오 4 앞 5 뒤
Dice[0] = 6;
Dice[1] = 1;
Dice[2] = 4;
Dice[3] = 3;
Dice[4] = 5;
Dice[5] = 2;
}
2. 주사위 이동 (makeMoveDice 함수)
주사위를 이동시키는 함수입니다. 이동 방향에 따라 주사위의 각 면의 값이 어떻게 변하는지 정의합니다.
void makeMoveDice(int goTo) {
int d0, d1, d2, d3, d4, d5;
d0 = Dice[0]; d1 = Dice[1]; d2 = Dice[2];
d3 = Dice[3]; d4 = Dice[4]; d5 = Dice[5];
if (goTo == 0) { // 오른쪽
Dice[0] = d3;
Dice[1] = d2;
Dice[2] = d0;
Dice[3] = d1;
}
else if (goTo == 1) { // 위쪽
Dice[0] = d5;
Dice[1] = d4;
Dice[4] = d0;
Dice[5] = d1;
}
else if (goTo == 2) { // 왼쪽
Dice[0] = d2;
Dice[1] = d3;
Dice[2] = d1;
Dice[3] = d0;
}
else { // 아래쪽
Dice[0] = d4;
Dice[1] = d5;
Dice[4] = d1;
Dice[5] = d0;
}
}
3. 입력 및 초기화 (Input 함수)
게임의 크기(N, M)와 이동 횟수(K)를 입력받고, 각 칸의 값을 입력받아 2차원 배열을 초기화합니다.
void Input() {
cin >> N >> M >> K;
Arr.resize(N);;
Score.resize(N);
visited.resize(N);
initDice();
for (int i = 0; i < N; i++) {
Arr[i].resize(M);
Score[i].resize(M);
visited[i].resize(M, false);
}
for (int i = 0; i < N; i++) {
for (int k = 0; k < M; k++) {
cin >> Arr[i][k];
}
}
}
4. 점수 계산 (makeScoreMap 함수)
주사위가 놓인 칸의 점수를 계산합니다. BFS 알고리즘을 사용하여 연결된 같은 값의 칸의 수를 세고, 이를 바탕으로 점수를 계산합니다.
void makeScoreMapSub(int sero, int garo) {
queue<Node> myQueue;
vector<Node> index;
index.push_back({ sero,garo });
myQueue.push({ sero,garo });
visited[sero][garo] = true;
int nowScore = Arr[sero][garo];
int resultScore = 0;
int count = 1;
while (!myQueue.empty()) {
int nowSero = myQueue.front().first;
int nowGaro = myQueue.front().second;
myQueue.pop();
for (int i = 0; i < 4; i++) {
int nextSero = nowSero + dy[i];
int nextGaro = nowGaro + dx[i];
if (isInside(nextSero, nextGaro) == false) continue;
if (visited[nextSero][nextGaro] == true) continue;
if (Arr[nextSero][nextGaro] == nowScore) {
myQueue.push({ nextSero,nextGaro });
index.push_back({ nextSero,nextGaro });
visited[nextSero][nextGaro] = true;
count++;
}
}
}
resultScore = count * nowScore;
for (int i = 0; i < index.size(); i++) {
Node node = index[i];
Score[node.first][node.second] = resultScore;
}
}
void makeScoreMap() {
for (int i = 0; i < N; i++) {
for (int k = 0; k < M; k++) {
if (visited[i][k] == true) continue;
makeScoreMapSub(i, k);
}
}
}
5. 게임 진행 (GameStart 함수)
주사위를 굴리며 게임을 진행하고 점수를 계산합니다. 주사위의 상태와 현재 위치를 바탕으로 다음 이동 방향을 결정하고, 주사위를 굴린 후 점수를 누적합니다.
void getGoToNumber(int sero, int garo) {
int nowDiceNumber = Dice[0];
if (nowDiceNumber > Arr[sero][garo]) {
nowGoTo = (4 + nowGoTo - 1) % 4;
}
else if (nowDiceNumber < Arr[sero][garo]) {
nowGoTo = (4 + nowGoTo + 1) % 4;
}
else if (nowDiceNumber == Arr[sero][garo]) {
nowGoTo = nowGoTo;
}
int nextSero = sero + dy[nowGoTo];
int nextGaro = garo + dx[nowGoTo];
if (isInside(nextSero, nextGaro) == false) {
nowGoTo = (4 + nowGoTo + 2) % 4;
}
}
int getScore(int sero, int garo) {
return Score[sero][garo];
}
void GameStart() {
makeScoreMap();
int nowSero = 0;
int nowGaro = 0;
for (int i = 0; i < K; i++) {
if (i == 0) {
makeMoveDice(0);
nowSero += dy[0];
nowGaro += dx[0];
ResultScore += getScore(nowSero, nowGaro);
}
else {
getGoToNumber(nowSero, nowGaro);
nowSero += dy[nowGoTo];
nowGaro += dx[nowGoTo];
makeMoveDice(nowGoTo);
ResultScore += getScore(nowSero, nowGaro);
}
}
}
[전체 코드]
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
typedef pair<int, int> Node;
int dy[4] = { 0,-1,0,1 };
int dx[4] = { 1,0,-1,0 };
vector<int> Dice;
vector<vector<int>> Arr;
vector<vector<int>> Score;
vector<vector<bool>> visited;
int N, M, K;
int nowGoTo = 0;
int ResultScore = 0;
void initDice() {
Dice.resize(6);
for (int i = 0; i <6; i++) {
Dice[i] = i;
}
//0 밑 1 위 2 왼 3오 4 앞 5 뒤
Dice[0] = 6;
Dice[1] = 1;
Dice[2] = 4;
Dice[3] = 3;
Dice[4] = 5;
Dice[5] = 2;
}
void makeMoveDice(int goTo) {
//오른쪽 0 위쪽 1 왼쪽 2 아래쪽 3
int d0, d1, d2, d3, d4, d5;
d0 = Dice[0]; d1 = Dice[1]; d2 = Dice[2];
d3 = Dice[3]; d4 = Dice[4]; d5 = Dice[5];
if (goTo == 0) {
Dice[0] = d3;
Dice[1] = d2;
Dice[2] = d0;
Dice[3] = d1;
}
else if (goTo == 1) {
Dice[0] = d5;
Dice[1] = d4;
Dice[4] = d0;
Dice[5] = d1;
}
else if (goTo == 2) {
Dice[0] = d2;
Dice[1] = d3;
Dice[2] = d1;
Dice[3] = d0;
}
else {
Dice[0] = d4;
Dice[1] = d5;
Dice[4] = d1;
Dice[5] = d0;
}
}
void Input() {
cin >> N >> M >> K;
Arr.resize(N);;
Score.resize(N);
visited.resize(N);
initDice();
for (int i = 0; i < N; i++) {
Arr[i].resize(M);
Score[i].resize(M);
visited[i].resize(M, false);
}
for (int i = 0; i < N; i++) {
for (int k = 0; k < M; k++) {
cin >> Arr[i][k];
}
}
}
bool isInside(int sero, int garo) {
if (sero >= 0 && sero < N && garo >= 0 && garo < M)return true;
return false;
}
void makeScoreMapSub(int sero, int garo) {
queue<Node> myQueue;
vector<Node> index;
index.push_back({ sero,garo });
myQueue.push({ sero,garo });
visited[sero][garo] = true;
int nowScore = Arr[sero][garo];
int resultScore = 0;
int count = 1;
while (!myQueue.empty()) {
int nowSero = myQueue.front().first;
int nowGaro = myQueue.front().second;
myQueue.pop();
for (int i = 0; i < 4; i++) {
int nextSero = nowSero + dy[i];
int nextGaro = nowGaro + dx[i];
if (isInside(nextSero, nextGaro) == false)continue;
if (visited[nextSero][nextGaro] == true)continue;
if (Arr[nextSero][nextGaro] == nowScore) {
myQueue.push({ nextSero,nextGaro });
index.push_back({ nextSero,nextGaro });
visited[nextSero][nextGaro] = true;
count++;
}
}
}
resultScore = count * nowScore;
for (int i = 0; i < index.size(); i++) {
Node node = index[i];
Score[node.first][node.second] = resultScore;
}
}
void makeScoreMap() {
for (int i = 0; i < N; i++) {
for (int k = 0; k < M; k++) {
if (visited[i][k] == true)continue;
makeScoreMapSub(i, k);
}
}
}
void Print() {
for (int i = 0; i < N; i++) {
for (int k = 0; k < M; k++) {
cout << Score[i][k] << " ";
}
cout << '\n';
}
}
void getGoToNumber(int sero, int garo) {
int nowDiceNumber = Dice[0];
if (nowDiceNumber > Arr[sero][garo]) {
nowGoTo = (4 + nowGoTo - 1) % 4;
}
else if (nowDiceNumber < Arr[sero][garo]) {
nowGoTo = (4 + nowGoTo + 1) % 4;
}
else if (nowDiceNumber == Arr[sero][garo]) {
nowGoTo = nowGoTo;
}
int nextSero = sero + dy[nowGoTo];
int nextGaro = garo + dx[nowGoTo];
if (isInside(nextSero, nextGaro) == false) {
nowGoTo = (4 + nowGoTo + 2) % 4;
}
}
int getScore(int sero, int garo) {
return Score[sero][garo];
}
void GameStart() {
makeScoreMap();
int nowSero = 0;
int nowGaro = 0;
for (int i = 0; i < K; i++) {
if (i == 0) {
makeMoveDice(0);
nowSero += dy[0];
nowGaro += dx[0];
ResultScore += getScore(nowSero, nowGaro);
}
else {
getGoToNumber(nowSero, nowGaro);
nowSero += dy[nowGoTo];
nowGaro += dx[nowGoTo];
makeMoveDice(nowGoTo);
ResultScore += getScore(nowSero, nowGaro);
}
}
}
int main(void) {
Input();
GameStart();
cout << ResultScore;
}
'백준 > 삼성기출문제' 카테고리의 다른 글
백준 14500 c++ "테트로미노" -PlusUltraCode- (1) | 2024.10.05 |
---|---|
백준 c++ 14499 "주사위 굴리기" -PlusUltraCode- (1) | 2024.07.05 |
백준 c++ 14890 "경사로" -PlusUltraCode- (0) | 2024.07.02 |
백준 17144 c++ "미세먼지 안녕!" -PlusUltraCode- (0) | 2024.06.26 |
백준 c++ 19236 "청소년 상어" -PlusUltraCode- (0) | 2024.06.24 |