본문 바로가기
알고리즘

백준 g3 1941 소문난 칠공주 c++

by kyj0032 2024. 1. 16.

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

 

1941번: 소문난 칠공주

총 25명의 여학생들로 이루어진 여학생반은 5×5의 정사각형 격자 형태로 자리가 배치되었고, 얼마 지나지 않아 이다솜과 임도연이라는 두 학생이 두각을 나타내며 다른 학생들을 휘어잡기 시작

www.acmicpc.net

 

풀이

DFS는 ㅜ자 형태의 경로가 안 된다.

전체 25자리 중 7자리를 고르는 25C7을 해도 충분히 시간 제한 안에 풀 수 있다.

 

next_permutation을 통해 25C7를 구하고, Y의 개수가 4개를 넘거나 인접하지 않으면 continue 하도록 했다

서로 인접해있는지는 BFS로 풀었고, prin 한 명을 시작점으로 해서 area가 7이 되지 않으면 인접하지 않다는 뜻이므로 false를 return했다.

 

소스 코드

/*boj g3 1941 소문난 칠공주*/
#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>

#define MAXN 6
using namespace std;

int N;
int answer = 0;
string board[MAXN];
vector<int> choice;

int prin[MAXN][MAXN];
int vis[MAXN][MAXN];

int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, -1, 0, 1};

void printVis() {
    cout << "\n=========================\n";
    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 5; j++) {
            cout << prin[i][j] << " ";
        }
        cout << "\n";
    }
}

void initialize() {
    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 5; j++) {
            prin[i][j] = 0;
            vis[i][j] = 0;
        }
    }
}

pair<int, int> start;
void vecToPrin() {
    for (int i = 0; i < 25; i++) {
        if (choice[i] == 0) {
            int x = i / 5;
            int y = i % 5;

            prin[x][y] = 1;

            start.first = x;
            start.second = y;
        }
    }
}

int getYCnt() {
    int YCnt = 0;

    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 5; j++) {
            if (prin[i][j] == 1) {
                if (board[i][j] == 'Y')
                    YCnt++;
            }
        }
    }

    return YCnt;
}

bool isAdj() { // 서로 인접해 있는지
    queue<pair<int, int>> Q;

    vis[start.first][start.second] = 1;
    Q.push({start.first, start.second});
    int cnt = 0;

    while (!Q.empty()) {
        cnt++;
        pair<int, int> cur = Q.front();
        Q.pop();

        for (int dir = 0; dir < 4; dir++) {
            int nx = cur.first + dx[dir];
            int ny = cur.second + dy[dir];

            if (nx < 0 || nx >= 5 || ny < 0 || ny >= 5) continue;
            if (vis[nx][ny] > 0) continue;
            if (prin[nx][ny] == 0) continue;

            vis[nx][ny] = vis[cur.first][cur.second] + 1;
            Q.push({nx, ny});
        }
    }

    if (cnt == 7)
        return true;
    else
        return false;
}

int main(void) {
    ios::sync_with_stdio(0);
    cin.tie(0);
    for (int i = 0; i < 5; i++) {
        cin >> board[i];
    }

    for (int i = 0; i < 7; i++)
        choice.push_back(0);
    for (int i = 0; i < 18; i++)
        choice.push_back(1);

    do {
        initialize();
        vecToPrin();

        if (getYCnt() >= 4) continue;
        if (!isAdj()) continue;
        // printVis();
        answer++;
    } while (next_permutation(choice.begin(), choice.end()));

    cout << answer << '\n';
}

'알고리즘' 카테고리의 다른 글

백준 g1 1799 비숍 c++  (0) 2024.01.17
백준 g1 18809 Gaaaaaaaaaarden c++  (0) 2024.01.17
백준 g5 16987 계란으로 계란치기 c++  (0) 2024.01.16
백준 g5 1759 암호 만들기 c++  (0) 2024.01.16
백준 15665 N과 M (11) c++  (0) 2024.01.15