[적용한 알고리즘]

브루트 포스, 재귀

 

[아이디어]

1. 한칸만 정하고 인접한 3칸만 이동하면 1가지 경우를 제외하고 전부 나타낼 수 있다.

2. 예외 케이스는 따로 처리해준다

 

[생각의 흐름 / 절차] 

1. 모양을 다해봐야하나? 너무 노가다여서 하기가 싫었다. 모양 간의 공통점을 찾고싶었다.

(ㅗ) 모양을 제외하면 나머지는 인접하게 붙은 4칸의 모양이었다. 

 

2. 경우의 수를 다 해봐야겠다. 한칸만 정하면 대부분의 경우의 수 표현가능,

나머지 한가지 (ㅗ,ㅜ,ㅓ,ㅏ) 모양은 따로 예외케이스 처리해서 빼줘야겠다.

 

3. 다음 칸으로 이동할때 dfs와는 동일하게 check 배열에 체크를 해주고,

재귀를 돌고 나올 때 check를 해제해줘야겠다.

-> 그래야 다른 점에서 시작하는 경우를 계산할 수 있으니까.

중복은 생기겠지만, 고려하지 않아도 된다. 어차피 최댓값만 구하면 되니까.

 

4. 모든 칸마다 반복문을 돌면서 실행해서 최댓값을 정해야겠다.

 

 

[교훈]

열심히 예외 케이스 처리하자. 이런 식으로 최대한 같은 걸로 묶고 예외로 빼줘야할 수도 있다. 

 

<코드>

#include <cstdio>
#include <algorithm>
#define SIZE 501
using namespace std;

int map[SIZE][SIZE];
bool check[SIZE][SIZE];
int dirx[] = {-1, 1, 0, 0};
int diry[] = {0, 0, -1, 1};
int n, m;
int ans = 0;

void tetrimino(int cnt, int curx, int cury, int sum){
    if (cnt == 4){
        ans = max(ans, sum);
        return;
    }

    if (check[curx][cury]) return;

    check[curx][cury] = true;

    for (int k = 0; k < 4; k++){
        int nx = curx + dirx[k];
        int ny = cury + diry[k];

        if (0 <= nx && nx < n && 0 <= ny && ny < m){
            tetrimino(cnt + 1, nx, ny, sum + map[curx][cury]);
        }
    }

    check[curx][cury] = false;
}

int tetrimino2(int curx, int cury){
    int ret = -1;
    int tempSum = 0;
    //세로 방향
    if (curx + 2 < n){
        tempSum = map[curx][cury] + map[curx + 1][cury] + map[curx + 2][cury];
        if (cury + 1 < m){
            int temp = tempSum + map[curx + 1][cury + 1];
            ret = max(ret, temp);
        }
        if (cury - 1 >= 0){
            int temp = tempSum + map[curx + 1][cury - 1];
            ret = max(ret, temp);
        }
    }

    //가로 방향
    if (cury + 2 < m){
        tempSum = map[curx][cury] + map[curx][cury + 1] + map[curx][cury + 2];
        if (curx + 1 < n){
            int temp = tempSum + map[curx + 1][cury + 1];
            ret = max(ret, temp);
        }
        if (curx - 1 >= 0){
            int temp = tempSum + map[curx - 1][cury + 1];
            ret = max(ret, temp);
        }
    }

    return ret;
}

int main(){
    scanf("%d %d", &n, &m);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            scanf("%d", &map[i][j]);
        }
    }

    for (int i = 0; i < n; i++){
        for (int j = 0; j < m; j++){
            tetrimino(0, i, j, 0);
            ans = max(ans, tetrimino2(i, j));
        }
    }

    printf("%d\n", ans);
    return 0;
}

'Algorithm > BOJ' 카테고리의 다른 글

[백준] 1759번 암호만들기  (124) 2019.11.12
[백준] 16197번 두 동전  (124) 2019.11.10
[백준] 15658번 연산자 끼워넣기 (2)  (124) 2019.11.08
[백준] 14888번 연산자 끼워넣기  (124) 2019.11.08
[백준] 14225번 부분수열의 합  (0) 2019.11.08

+ Recent posts