본문 바로가기

Coding Test

백준 2615 오목

https://www.acmicpc.net/problem/2615

#include <iostream>
#include <vector>

using namespace std;


vector<vector<int>> board(22, vector<int>(22, 0));

//하, 우, 우하대각선, 우상대각선 순
int ny[4] = {1, 0, 1, -1};
int nx[4] = {0, 1, 1, 1};

int main() {


    for (int i = 1; i <= 19; i++) {
        for (int j = 1; j <= 19; j++) {
            cin >> board[i][j];
        }
    }


    for (int i = 1; i <= 19; i++) {
        for (int j = 1; j <= 19; j++) {


            //현재 위치에 바둑돌이 있다면
            if (board[i][j]) {

                int cur = board[i][j];


                //방향
                for (int k = 0; k < 4; k++) {
                    int l = 1;  //현재 위치로부터 해당 방향의 같은 돌의 개수
                    int newY, newX;
                    //[i][j] 바둑돌로부터의 거리
                    while (1) {

                        newY = i + ny[k] * l;
                        newX = j + nx[k] * l;

                        //해당 위치가 바둑판의 범위를 넘어가는지 확인
                        if (newY < 1 || newY > 19 || newX < 1 || newX > 19) {
                            break;
                        } else if (cur != board[newY][newX]) {
                            break;
                        }

                        l++;

                    }

                    if (l == 5) {
                        if ((i - ny[k] < 1 || i - ny[k] > 19) || (j - nx[k] < 1 || j - nx[k] > 19)) {
                            cout << cur << "\n";
                            cout << i << " " << j << "\n";
                            return 0;
                        } else if (board[i - ny[k]][j - nx[k]] != cur) {
                            cout << cur << "\n";
                            cout << i << " " << j << "\n";
                            return 0;
                        }
                    }
                }
            }
        }
    }

    cout << 0;

    return 0;
}

1. 문제

 현재진행중인 오목 판과 그 위의 바둑돌의 현황이 주어진다. 6목 이상은 허용하지 않는다고 했을 때, 오목의 승패 여부, 판가름났을 경우 승자와 승리 조건에 해당하는 바둑돌 중 가장 좌측에 있는 바둑돌의 위치를 출력한다.

2. 풀이

브루트포스인데 고려해야 할 점이 좀 많았다. 우선 바둑돌을 셀 수 있는 방향은 여덟방향이다. 그 중 오목이 성립되었을 때, 첫 번째 돌의 위치가 가장 좌측에 있는 경우는 우, 우하, 하, 우상으로 네 가지이다. 이 방향을 배열에 입력해준다.

//하, 우, 우하대각선, 우상대각선 순
int ny[4] = {1, 0, 1, -1};
int nx[4] = {0, 1, 1, 1};

 

바둑돌을 입력받고 오목판의 모든 위치에 대해 계산을 진행한다.

 //현재 위치에 바둑돌이 있다면
            if (board[i][j]) {

                int cur = board[i][j];


                //방향
                for (int k = 0; k < 4; k++) {
                    int l = 1;  //현재 위치로부터 해당 방향의 같은 돌의 개수
                    int newY, newX;
                    //[i][j] 바둑돌로부터의 거리
                    while (1) {

                        newY = i + ny[k] * l;
                        newX = j + nx[k] * l;

                        //해당 위치가 바둑판의 범위를 넘어가는지 확인
                        if (newY < 1 || newY > 19 || newX < 1 || newX > 19) {
                            break;
                        } else if (cur != board[newY][newX]) {
                            break;
                        }

                        l++;

                    }

현재 위치에 바둑돌이 존재한다면(1, 2) 위치를 잡고, 위에서 정의한 각 방향에 대해 연속된 같은 바둑돌의 개수를 구하면서 따라간다. 가다가 연속이 끊기면 무한루프를 빠져나온다.

		if (l == 5) {
                        if ((i - ny[k] < 1 || i - ny[k] > 19) || (j - nx[k] < 1 || j - nx[k] > 19)) {
                            cout << cur << "\n";
                            cout << i << " " << j << "\n";
                            return 0;
                        } else if (board[i - ny[k]][j - nx[k]] != cur) {
                            cout << cur << "\n";
                            cout << i << " " << j << "\n";
                            return 0;
                        }
                    }

여기서 애를 좀 많이 먹었다. 만약 각 방향으로 수를 세어 확인한게 5개일 경우 출력하기 전에 확인해야 할 사항이 하나 더 있다. 

해당 위치에서 확인할 경우 우측으로 오목 조건을 만족했다고 바로 출력하면 6목을 고려할 수 없는 문제가 생긴다. 이를 해결하기 위해 나아갔던 방향의 반대방향 위치의 하나를 확인한다. 

 그 위치가 오목판을 벗어나거나, 벗어나지 않았는데 다른 바둑돌이거나 비어있을 경우 오목이 확정이므로 승리 여부와 해당 돌의 위치를 출력한다.

 

 모든 범위를 돌았는데도 오목이 발견되지 않으면 0을 출력하면 정답을 구할 수 있다.

'Coding Test' 카테고리의 다른 글

백준 12919 A와 B 2  (1) 2024.06.09
백준 15661 링크와 스타트  (1) 2024.06.08
백준 2961 도영이가 만든 맛있는 음식  (0) 2024.06.07
백준 14620 꽃길  (0) 2024.06.05
백준 9079 동전 게임  (0) 2024.06.04