알고리즘/문제 풀이

백준 3042번: 트리플렛

Themion 2022. 1. 18. 16:41

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

 

3042번: 트리플렛

상근이와 창영이는 트리플렛이라는 게임을 하고 있다. 이 게임을 하려면 칠판에 N*N 그리드를 그려야 한다. 그 다음 알파벳 대문자를 적절히 각 칸에 써 넣는다. 한 알파벳을 여러 칸에 쓸 수는

www.acmicpc.net

세 점 (x1, y1), (x2, y2), (x3, y3)가 한 직선에 있다면 (y2 - y1) / (x2 - x1) == (y3 - x3) / (y2 - x2)여야 한다. 이 때 double을 사용할 경우 오차가 발생할 수 있으므로 위 식을 정리하면 (y2 - y1)(x3 - x2) == (y3 - y2)(x2 - x1)이다.

주어진 조건에서 트리플렛은 세 알파벳이 직선을 이뤄야 한다고 되어 있다. 즉 세 알파벳 사이의 거리를 따지지 않으므로, 가능한 모든 세 알파벳에 대해 한 직선 위에 있는 세 알파벳 집합의 개수를 계산해 출력해야 한다.

#include <cstdio>

using namespace std;

#define MAX_ALP 26
#define y_(i) (crd[idx[i + 1]].y - crd[idx[i]].y)
#define x_(i) (crd[idx[i + 1]].x - crd[idx[i]].x)

// siz: crd의 길이, idx: 트리플렛 여부를 검토할 세 좌표의 crd 인덱스
int siz, idx[3];
// 칠판에서 각 알파벳의 좌표를 정렬된 순서로 저장
struct coord{ char y = 0, x = 0; } crd[MAX_ALP];

// len개의 알파벳을 골랐고 마지막으로 고른 알파벳이 last번째 알파벳일 때
int brute_force(int len, int last) {
    // 주어진 경우에서 트리플렛의 개수
    int ret = 0;
    
    // 만일 세 알파벳을 모두 골랐다면 세 알파벳이 일직선상에 있는지 여부를 계산
    // y_(0) : y_(1) == x_(0) : x_(1)이라면 세 알파벳의 좌표의 변위가 같으므로
    // 세 알파벳은 일직선상에 있고
    // 식을 변형하면 y_(0) * x_(1) == y_(1) * x_(0)이다
    if (len == 3) ret = y_(0) * x_(1) == y_(1) * x_(0);
    // 그렇지 않다면 남은 3 - len개의 알파벳을 골랐을 때 트리플렛의 개수를 계산
    else for (int i = last; i <= siz - (3 - len); i++) {
        // 트리플렛의 len번째 알파벳을 i번째 알파벳으로 고른 뒤
        idx[len] = i;
        // 이 경우에 트리플렛의 개수를 전부 더해 ret에 저장
        ret += brute_force(len + 1, i + 1);
    }

    // 현재 경우에서 트리플렛의 수를 반환
    return ret;
} 

int main() {
    // 그리드의 크기
    int N;
    // 그리드의 각 좌표의 상태를 입력받아 알파벳이 놓인 그리드의 좌표를 crd에 저장
    scanf("%d", &N);
    for (char y = 0; y < N; y++) {
        getchar();
        for (char x = 0; x < N; x++) if (getchar() != '.') crd[siz++] = { y, x };
    }

    // 트리플렛인 모든 경우를 계산해 경우의 수를 출력
    printf("%d\n", brute_force(0, 0));

    return 0;
}

'알고리즘 > 문제 풀이' 카테고리의 다른 글

백준 15973번: 두 박스  (0) 2022.01.20
백준 7347번: 플립과 시프트  (0) 2022.01.19
백준 18222번: 투에-모스 문자열  (0) 2022.01.18
백준 1105번: 팔  (0) 2022.01.17
백준 9659번: 돌 게임 5  (0) 2022.01.17