https://www.acmicpc.net/problem/19236
이 코드는 주어진 4x4 격자에서 물고기들을 먹으면서 최종 점수를 최대로 만드는 문제를 해결하는 코드입니다. 각 물고기는 고유의 번호와 이동 방향을 가지고 있으며, 상어가 이 물고기들을 먹으며 이동할 때 가능한 최대 점수를 계산합니다.
주요 변수와 함수 설명
- 전역 변수
- vector<vector<Node>> cArr: 격자의 상태를 저장하는 2차원 벡터. 각 원소는 (물고기 번호, 방향) 쌍을 나타냅니다.
- int resultMax: 상어가 얻을 수 있는 최대 점수를 저장.
- int Result: 현재 상어가 얻은 점수.
- int fishCount: 현재 남아 있는 물고기 수.
- vector<bool> visited: 물고기의 방문 여부를 확인하는 벡터.
- 함수
- void Input(): 입력을 받아 격자 상태를 초기화.
- bool isInside(int sero, int garo): 주어진 좌표가 격자 내에 있는지 확인.
- bool findDir(int nowSero, int nowGaro): 현재 위치의 물고기가 이동할 수 있는 방향을 찾고, 이동 가능한 경우 방향을 변경.
- void swap(int nowSero, int nowGaro): 현재 물고기와 이동할 위치의 물고기를 교환.
- int eatFish(int nowSero, int nowGaro): 현재 위치의 물고기를 먹고 점수를 추가.
- Node findMinFish(): 현재 방문하지 않은 물고기 중 가장 작은 번호를 가진 물고기의 위치를 찾음.
- void fishRotation(): 모든 물고기를 번호 순서대로 이동.
- void DFS(int nowSero, int nowGaro): 깊이 우선 탐색을 사용하여 가능한 모든 경로를 탐색하고, 최대 점수를 계산.
- void Print(): 격자의 상태를 출력(디버깅용).
코드 풀이 과정
- 입력 받기
- Input() 함수에서 4x4 격자의 상태를 입력받아 초기화합니다.
- 초기 설정
- 상어가 첫 번째 물고기를 먹습니다(eatFish(0, 0)).
- 물고기 수를 1 감소시킵니다.
- DFS 호출
- 상어가 (0, 0)에서부터 DFS를 시작합니다(DFS(0, 0)).
- DFS 함수
- 현재 위치의 물고기의 방향을 가져옵니다.
- 물고기들을 이동시킵니다(fishRotation()).
- 상어가 이동할 수 있는 모든 방향에 대해 재귀적으로 탐색합니다.
- 상어가 이동할 때마다 현재 상태를 저장하고, 점수를 갱신하며, 이동 후 원래 상태로 되돌리는 백트래킹을 수행합니다.
- 결과 출력
- 상어가 얻을 수 있는 최대 점수를 출력합니다.
핵심 로직
- 물고기 이동: 모든 물고기는 번호 순서대로 이동하며, 이동 가능한 방향을 찾습니다.
- 상어 이동: 상어는 현재 위치에서 물고기의 방향으로 1~3칸 이동할 수 있으며, 이동 가능한 모든 경우를 재귀적으로 탐색합니다.
- 백트래킹: 상어의 모든 이동을 시도해보고, 점수가 더 높은 경우를 찾아내어 최대 점수를 갱신합니다.
이 과정을 통해 상어가 얻을 수 있는 최대 점수를 계산합니다.
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
typedef pair<int, int> Node;
int dy[8] = { -1,-1,0,1,1,1,0,-1 };
int dx[8] = { 0,-1,-1,-1,0,1,1,1 };
int resultMax = -1;
vector<vector<Node>> cArr;
int Result = 0;
int fishCount = 16;
void Input() {
cArr.resize(4);
for (int i = 0; i < 4; i++) {
cArr[i].resize(4);
}
for (int i = 0; i < 4; i++) {
for (int k = 0; k < 4; k++) {
int num;
int dir;
cin >> num >> dir;
cArr[i][k] = { num,dir-1 };
}
}
}
bool isInside(int sero, int garo) {
if (sero >= 0 && sero < 4 && garo >= 0 && garo < 4) {
return true;
}
return false;
}
bool findDir(int nowSero, int nowGaro ) {
int nowDirection = cArr[nowSero][nowGaro].second;
int nextDirection = nowDirection;
int flag = 0;
while (1) {
int nextSero = nowSero + dy[nextDirection];
int nextGaro = nowGaro + dx[nextDirection];
if (isInside(nextSero,nextGaro) == false || cArr[nextSero][nextGaro].first == 0) {
nextDirection = (nextDirection + 1) % 8;
if (nextDirection == nowDirection)break;
}
else {
flag = 1;
break;
}
}
if (flag == 1) {
cArr[nowSero][nowGaro].second = nextDirection;
return true;
}
else {
return false;
}
}
void swap(int nowSero, int nowGaro) {
int direction = cArr[nowSero][nowGaro].second;
int nextSero = nowSero + dy[direction];
int nextGaro = nowGaro + dx[direction];
Node temp = { cArr[nextSero][nextGaro].first,cArr[nextSero][nextGaro].second };
cArr[nextSero][nextGaro] = cArr[nowSero][nowGaro];
cArr[nowSero][nowGaro].first = temp.first;
cArr[nowSero][nowGaro].second = temp.second;
}
int eatFish(int nowSero, int nowGaro) {
int backResult = cArr[nowSero][nowGaro].first;
Result += cArr[nowSero][nowGaro].first;
cArr[nowSero][nowGaro].first = 0;
if (Result > resultMax)resultMax = Result;
return backResult;
}
vector<bool> visited;
Node findMinFish() {
int minNumber = 999;
Node index = { -1,-1 };
for (int i = 0; i < 4; i++) {
for (int k = 0; k < 4; k++) {
if (cArr[i][k].first <= 0)continue;
if (visited[cArr[i][k].first] == false)continue;
if (cArr[i][k].first < minNumber) {
minNumber = cArr[i][k].first;
index = { i,k };
}
}
}
if(minNumber!=999)visited[minNumber] = false;
return index;
}
void fishRotation() {
visited.clear();
visited.resize(17,true);
for (int i = 0; i < fishCount; i++) {
Node index = findMinFish();
int nowSero = index.first;
int nowGaro = index.second;
if (findDir(nowSero, nowGaro) == true) {
swap(nowSero, nowGaro);
}
}
}
void DFS(int nowSero,int nowGaro) {
vector<vector<Node>> copyArr;
int direction = cArr[nowSero][nowGaro].second;
fishRotation();
for (int i = 1; i <= 3; i++) {
int nextSero = nowSero + dy[direction]*i;
int nextGaro = nowGaro + dx[direction] * i;
if (isInside(nextSero, nextGaro) == false)continue;
if (cArr[nextSero][nextGaro].first == -1)continue;
copyArr = cArr;
cArr[nowSero][nowGaro].first = -1;
fishCount--;
int backResult =eatFish(nextSero, nextGaro);
DFS(nextSero, nextGaro);
Result -= backResult;
fishCount++;
cArr = copyArr;
}
}
void Print() {
for (int i = 0; i < 4; i++) {
for (int k = 0; k < 4; k++) {
cout << cArr[i][k].first << " " << cArr[i][k].second << " ";
}
cout << '\n';
}
}
int main(void) {
Input();
int no = eatFish(0, 0);
fishCount--;
DFS(0, 0);
cout << resultMax;
}
'백준 > 삼성기출문제' 카테고리의 다른 글
백준 14500 c++ "테트로미노" -PlusUltraCode- (1) | 2024.10.05 |
---|---|
백준 c++ 14499 "주사위 굴리기" -PlusUltraCode- (1) | 2024.07.05 |
백준 c++ 14890 "경사로" -PlusUltraCode- (0) | 2024.07.02 |
백준 c++ 23288 "주사위 굴리기2" -PlusUltraCode- (0) | 2024.06.28 |
백준 17144 c++ "미세먼지 안녕!" -PlusUltraCode- (0) | 2024.06.26 |