본문 바로가기
Programming/Algorithm

swe 2115 벌꿀채취

by OKOK 2018. 4. 12.

- dfs + dfs

- dfs 로 먼저 벌통의 영역을 선정한 후에

- 선정된 벌통에 대해서 dfs 를 통해서 최대 벌꿀량을 계산합니다.


- dfs + dfs 둘다 풀으니 왕뿌듯합니당. 


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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/*
2121 벌꿀 채취 시작
채취하여 얻을 수 있는 수익의 합이 최대.
40분 컷
중복 x, 조합입니다. 
1. 두 명의 벌의 선택한 영역. dfs (중복 x, 조합)
2. 선택된 곳에서 최대 양이 나올 수 있도록 계산하기.
2-1. 숫자를 합해서, 10이 넘어가지 안도록 하고, 그것들의 개별 곱을 저장해두기.
dfs 중복 x, 조합입니다.
*/
 
#include <iostream>
#include <algorithm>
using namespace std;
#define SIZE 11
 
int map[SIZE][SIZE];
int visit[SIZE][SIZE];
int ans;
int N, M, C;
int maxVal = 0;
int maxVal2 = 0;
int maxVal3 = 0;
int isFine;
int tong[2][5]; // 1 에는 하나, 2에도 하나씩 저장합니다. 통의 최대 크기는 5
int index;
 
void problemIn() {
    cin >> N >> M >> C;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            cin >> map[i][j];
        }
    }
}
 
void init() {
    maxVal = maxVal2= maxVal3 =0;
}
 
/*
현재 tong[1] = { 7,2,9}
tong[2] = {6,6,6};
안의 숫자의 합이 10 이전이면, 제곱값을 저장합니다.
독립적으로 진행가능합니다. 먼저 통1에 대해서 진행합니다.
*/
 
void dfs2(int pos, int sum, int square) {
    if (pos == M) {
        maxVal = max(maxVal, square);
        return;
    }
    if (sum + tong[0][pos] <= C) {
        dfs2(pos + 1, sum + tong[0][pos], square + pow(tong[0][pos], 2));
    }
    dfs2(pos + 1, sum, square);
}
void dfs3(int pos, int sum, int square) {
    if (pos == M) {
        maxVal2 = max(maxVal2, square);
        return;
    }
    if (sum + tong[1][pos] <= C) {
        dfs3(pos + 1, sum + tong[1][pos], square + pow(tong[1][pos], 2));
    }
    dfs3(pos + 1, sum, square);
}
 
void check() {
    maxVal = maxVal2 = 0;
    dfs2(000);
    dfs3(000);
    maxVal3 = max(maxVal3, maxVal + maxVal2);
}
 
 
/*
벌통 선택 2개 하기,
중복을 최소화하기 위한 변수 startI
*/
void dfs(int depth, int startI) {
 
    if (depth == 2) {
        check();
        return;
    }
 
    for (int i = startI; i < N; i++) {
        for (int j = 0; j < (N - M + 1); j++) {
            // 중복 피하기.
            for (int l = 0; l < M; l++) {
                if (visit[i][j + l] == 0) {
                    isFine = 1;
                }
                else {
                    isFine = 0;
                    break;
                }
            }
            if (isFine) {
                index = 0;
                for (int k = 0; k < M; k++) {
                    visit[i][j + k] = 1;
                    tong[depth][index] = map[i][j + k];
                    index++;
                }
                dfs(depth + 1, startI);
                for (int k = 0; k < M; k++) {
                    visit[i][j + k] = 0;
                }
            }
        }
    }
}
 
void solve() {
    dfs(00);
}
 
int main() {
    int T;
    cin >> T;
    for (int tc = 1; tc <= T; tc++) {
        problemIn();
        solve();
        cout << "#" << tc << " " << maxVal3 << endl;
        init();
    }
    return 0;
}
cs