Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
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
Tags
more
Archives
Today
Total
관리 메뉴

대웅짱님의 블로그

[14500] 테트로미노 본문

알고리즘/BOJ

[14500] 테트로미노

대웅짱 2019. 2. 12. 22:34

문제: https://www.acmicpc.net/problem/14500


이번 문제는 테트로미노이다.


주어진 다섯 가지 도형 중 딱 하나만을 사용해 종이에 올려 놓았을 때


가장 큰 값을 구하는 문제이다.


예전에 한 번 풀고 이번 기회에 다시 풀어서 풀이가 두 가지가 있다.


매우 비슷하지만 약간 차이가 있으니 둘 다 소개하겠다.


사실 똑같은 방법이긴 하다.


먼저 첫 번째 방법은


도형을 잘 살펴보면 알겠지만 T 모양의 도형을 제외하고 나머지 도형들은 한 붓그리기 처럼


처음 점에서 마지막 점 까지 쭉 연결할 수 있다.


이걸 이용해 상 하 좌 우 를 숫자로 세 자리 순열을 만든다. ex) 111 ~ 444


처음 점과 이 세 자리 순열을 이용해 도형을 만든다.


이때 주의해야할 점은 아래 -> 위, 왼 쪽 -> 오른 쪽와 같이 반대 방향으로 가면 도형이 만들어지지 않는다.


이런 순열은 버리고 각 도형의 최대 값을 찾으면 된다.


그 후 T 모양 도형은 따로 구해 준 후 이들 중 최대 값을 구하면 된다.



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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include<cstdio>
#include<algorithm>
using namespace std;
int n, m, arr[550][550], maxi;
int disc[5];
int dx[5= { 0010-1 };
int dy[5= { 010-10 };
 
int tx[4= { 0001 };
int ty[4= { 0121 };
int mx[4= { 1-11-1 };
int my[4= { 11-1-1 };
 
void tShape(int x, int y) {
    int nx, ny, ret;
    for (int i = 0; i < 4; i++) {
        ret = arr[x][y];
        for (int j = 1; j <= 3; j++) {
            nx = x + tx[j] * mx[i];
            ny = y + ty[j] * my[i];
            if (nx < 0 || nx >= n || ny < 0 || ny >= m) break;
            ret += arr[nx][ny];
        }
        maxi = max(maxi, ret);
        ret = arr[x][y];
        for (int j = 1; j <= 3; j++) {
            nx = x + ty[j] * my[i];
            ny = y + tx[j] * mx[i];
            if (nx < 0 || nx >= n || ny < 0 || ny >= m) break;
            ret += arr[nx][ny];
        }
        maxi = max(maxi, ret);
    }
}
void func(int x, int y, int num, int last) {
    if (num == 4) {
        int nx, ny;
        nx = x; ny = y;
        int ret = arr[nx][ny];
        
        for (int i = 1; i <= 3; i++) {
            nx += dx[disc[i]];
            ny += dy[disc[i]];
            if (nx < 0 || nx >= n || ny < 0 || ny >= m) break;
            ret += arr[nx][ny];
        }
 
        maxi = max(maxi, ret);
        
        return;
    }
    for (int i = 1; i <= 4; i++) {
        if (abs(i - last) == 2continue;
        disc[num] = i;
        func(x, y, num + 1, i);
        disc[num] = 0;
    }
}
 
int main() {
    scanf("%d %d"&n, &m);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            scanf("%d"&arr[i][j]);
        }
    }
 
    maxi = 0;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            func(i, j, 1-10);
            tShape(i, j);
        }
    }
    printf("%d\n", maxi);
 
    return 0;
}
cs



두 번째 방법은 다 똑같은데 위에서 말한 순열을 조금만 다르게 생각해서 풀었다.


생각해보면 한 붓 그리기처럼 그릴 수 있다는 말은 그냥 그 점에서 길이가 4인 DFS를 말한다.


그러므로 현재 점에서 DFS를 수행하고 길이가 4가 된 순간 최대 값을 갱신해주면 된다.


T도형은 마찬가지로 따로 구해주었다.


끝.




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
#include<cstdio>
#include<algorithm>
using namespace std;
int n, m, maxi;
int arr[555][555];
bool visit[555][555];
int dx[4= {001-1};
int dy[4= {1-100};
int shapeX[4][4= {{0121}, {0121}, {000-1}, {0001}};
int shapeY[4][4= {{0001}, {000-1}, {0121}, {0121}};
void dfs(int x, int y, int cnt, int sum){
    if(cnt == 4){
        maxi = max(maxi, sum);
        return ;
    }
    for(int i=0;i<4;i++){
        int nx = x+dx[i];
        int ny = y+dy[i];
        if(nx<0 || nx>=|| ny<0 || ny>=|| visit[nx][ny]) continue;
        visit[nx][ny] = 1;
        dfs(nx, ny, cnt+1, sum+arr[nx][ny]);
        visit[nx][ny] = 0;
    }
}
 
int main(){
    scanf("%d %d"&n, &m);
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            scanf("%d"&arr[i][j]);
        }
    }
    maxi = 0;
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            visit[i][j] = 1;
            dfs(i, j, 1, arr[i][j]);
            visit[i][j] = 0;
 
            for(int p=0; p<4; p++){
                int sum = 0;
                for(int q=0; q<4; q++){
                    int nx = i+shapeX[p][q];
                    int ny = j+shapeY[p][q];
                    if(nx<0 || nx>=|| ny<0 || ny>=m) 
                        break;
                    sum += arr[nx][ny];
                }
                maxi = max(maxi, sum);
            }
        }
    }
 
    printf("%d\n", maxi);
 
 
    return 0;
}
cs


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

[14502] 연구소  (0) 2019.02.14
[14501] 퇴사  (0) 2019.02.13
[14499] 주사위 굴리기  (0) 2019.02.09
[13458] 시험 감독  (0) 2019.02.09
[3190] 뱀  (0) 2019.02.08