알고리즘 문제/[백준]

[백준] 14500번: 테트로미노

latter2005 2020. 12. 5. 21:54

문제 주소 : www.acmicpc.net/problem/14500

 

14500번: 테트로미노

폴리오미노란 크기가 1×1인 정사각형을 여러 개 이어서 붙인 도형이며, 다음과 같은 조건을 만족해야 한다. 정사각형은 서로 겹치면 안 된다. 도형은 모두 연결되어 있어야 한다. 정사각형의 변

www.acmicpc.net

문제 확인

 

모든 루프를 제거하고 조건식으로 풀 수 있는 문제이지만 이는 너무 시간이 많이 드는 작업이라 간단하게 dfs와 가지치기를 통해 풀었습니다. 조건식 풀이로 푼다면 시간과 메모리 모두 단축할 수 있습니다.

테트로미노는 최대 4개까지의 도형이므로 탐색이 깊지 않으므로 dfs로 풀어도 무방합니다.

주의해야 할 점은 다른 4가지의 테트로미노는 dfs로 풀 수 있지만 ㅜ 모양의 테트로미노는 dfs를 통해 구현할 수 없으므로 따로 작업을 해 주어야 합니다.

 

풀이

 

배열에 값을 입력받을 시 가지치기를 위한 최댓값을 미리 기록 해 둡니다.

후 dfs를 통해 탐색하여 최댓값을 찾습니다. 이때 최대 탐색 깊이가 4이므로 그전에 탐색했던 칸으로 돌아가지만 않으면

visited 배열을 사용하지 않고 잘못된 탐색을 배제할 수 있습니다. 이는 xor을 통해 전의 방향과 비교하여 구형하였습니다.

최댓값을 통해 남은 횟수 * max 값을 이용하여 현재까지의 최댓값을 넘지 못한다면 탐색을 종료하여 탐색 횟수를 줄일 수 있습니다.

ㅜ 모양의 테트로미노는 따로 함수를 두어 구합니다.

 

코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <cstdio>
 
#include <unistd.h>
namespace io {
    const signed IS = 1 << 13, OS = 1 << 20;
    char I[IS + 1], *= I;
    //char O[OS], *K = O;
 
    inline void daer() { if (J >= I + IS - 64) { char*= I; do*p++ = *J++while (J != I + IS); p[read(0, p, I + IS - p)] = 0; J = I; } }
    template<int N = 10typename T = int> inline T getu() { daer(); T x = 0int k = 0do x = x * 10 + *- '0'while (*++>= '0'&&++< N); ++J; return x; }
    template<int N = 10typename T = int>inline  T geti() { daer(); bool e = *== '-'; J += e; return(e ? -1 : 1)*getu<N, T>(); }
    /*inline void flush() { write(1, O, K - O); K = O; }
    template<int N = 10, typename T = int> inline void putu(T n) { char s[(N + 7) / 8 * 8], *p = s; int k = 0; do*p++ = n % 10 + 48; while ((n /= 10) && ++k < N); do*K++ = *--p; while (p != s); *K++ = 10; if (K >= O + OS - 64)flush(); }
    template<int N = 10, typename T = int> inline void puti(T n) { if (n < 0)*K++ = '-', n = -n; putu<N, T>(n); }*/
    struct f { f() { I[read(0, I, IS)] = 0; }~f() { /*flush();*/ } }flu;
};//출처 : https://cgiosy.github.io/posts/fast-io
using namespace io;
short dx[] = { 0,0,-1,1,0,0 },
dy[] = { 1,-1,0,0,1,-1 }; // 동서북남
short ary[502][502];
int res, max;
void dfs(int x, int y, int b, int cnt, int val) {
    if (cnt == 4) {
        if (res < val)
            res = val;
        return;
    }
    if (res > (4 - cnt) * max + val)//기댓값
        return;
    for (int i = 0; i < 4; i++) {
        if (b == i) continue;//돌아가는 방향
        int nx = x + dx[i], ny = y + dy[i];
        if (ary[nx][ny] != 0)//배열 안
            dfs(nx, ny, i ^ 1, cnt + 1, val + ary[nx][ny]);
    }
}
inline void ex(int x, int y) {
    if (res > 3 * max + ary[x][y]) return;
    int tmp;
    for (int i = 0; i < 4; i++) {//ㅜ모양
        tmp = ary[x][y] + ary[dx[i] + x][dy[i] + y] + ary[dx[i + 1+ x][dy[i + 1+ y] + ary[dx[i + 2+ x][dy[i + 2+ y];
        if (tmp > res)
            res = tmp;
    }
}
int main() {
    int n = getu(), m = getu();
    for (int i = 1, j = 1; i <= n; i++, j = 1)
        while (j <= m) {
            ary[i][j] = getu();
            if (ary[i][j] > max)//기댓값 계산을 위한 최댓값
                max = ary[i][j];
            j++;
        }
    for (int i = 1, j = 1; i <= n; i++, j = 0)
        while (j <= m) {
            dfs(i, j, -11, ary[i][j]);
            ex(i, j++);
        }
    printf("%d", res);
 
}
cs
반응형

'알고리즘 문제 > [백준]' 카테고리의 다른 글

[백준] 19236 청소년 상어  (0) 2020.12.09
[백준] 16637 괄호 추가하기  (0) 2020.12.05
[백준] 16236번: 아기상어  (0) 2020.12.05
[백준] 1157번: 단어공부  (0) 2020.12.05
[백준] 20119번: 클레어와 물약  (0) 2020.12.03