SWEA::2115 벌꿀채취
겹치지 않도록 m개 고르는 경우에 대해 백트래킹
비용계산에 대해 백트래킹 을 해야하는 문제이다.
겹치지 않도록 m개 고르는 방법에 있어서 굉장히 많은 고생을 했고,
두가지 방법으로 풀어보았다.
첫 번째 방법 : 먼저 m개를 고르고 그 이후에 나올 수 있는 모든 조합에 대해 골라 최대값 찾기
두 번째 방법 : 각각 벌통에 대해 올 수 있는 최댓값을 저장시킨 후 m개 씩 2개 골라 최대값 찾기
두 번째 방법이 훨씬 연산이 적어진다.
이유:
첫번째 방법으로 1 2 3 4 5 에서 2개를 고른다고 할때
1 2//1 3//1 4//1 5//2 3//2 4//2 5// ... // 4 5 ---> 이런식으로 중복되어 비용을 계산해야 하는 부분이 생긴다. 그러나 두번째 방법을 이용하면 중복되어 계산하는 부분이 없어지게 되므로 더 빠르게 문제해결이 가능하다.
<첫번째 방법>
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 | #include <stdio.h> #include <memory.h> int map[10][10]; bool visited[10][10]; int n, m, c, res; int max(int a, int b) { return (a > b) ? a : b; } //비용 구하기 void getPrice(int x, int y, int a, int sum, int price) { if (sum > c) return ; res = max(res, price); if (a == m) return; getPrice(x, y + 1, a + 1, sum + map[x][y], price + map[x][y] * map[x][y]); getPrice(x, y + 1, a + 1, sum, price); } int solve(int x, int y) { //먼저 고른 m개의 벌통에 대해 비용 구하기 for (int i = 0; i < m; i++) { visited[x][y + i] = true; } res = 0; getPrice(x, y, 0, 0, 0); int priceA = res; //나중에 고른 m개의 벌통에 대해 비용 구하며 비교하기 int priceB = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < n-m+1; j++) { if (!visited[i][j]) { res = 0; getPrice(i, j, 0, 0, 0); priceB = max(priceB, res); } } } return priceA + priceB; } void init() { memset(visited, 0, sizeof(visited)); } int main() { int t; scanf("%d", &t); for (int tc = 1; tc <= t; tc++) { init(); scanf("%d %d %d", &n, &m, &c); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { scanf("%d", &map[i][j]); } } int mm = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < n-m+1; j++) { mm = max(mm, solve(i, j)); } } printf("#%d %d\n", tc, mm); } } | cs |
<두번째 방법>
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 | #include <iostream> #include <vector> #include <algorithm> using namespace std; int t, n, m, c; int map[10][10]; int d[10][10]; //최대값 계산하기 int calc(vector<int> &v, int n, int sum, int val) { if (sum > c) return 0; if (n == v.size()) return val; return max(calc(v, n + 1, sum + v[n], val + v[n] * v[n]), calc(v, n + 1, sum, val)); } // 최대값 찾기 int getMaxPrice(int x,int y) { vector<int> v; for (int i = 0; i < m; i++) { v.push_back(map[x][y + i]); } return calc(v, 0, 0, 0); } int dfs(int x,int y) { int ans = 0; //같은라인 for (int i = y + m; i < n - m + 1; i++) { ans = max(ans, d[x][i]); } //다음라인 for (int i = x + 1; i < n; i++) { for (int j = 0; j < n; j++) { ans = max(ans, d[i][j]); } } return ans; } int main() { scanf("%d", &t); for (int tc = 1; tc <= t; tc++) { scanf("%d%d%d", &n, &m, &c); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { scanf("%d", &map[i][j]); d[i][j] = 0; } } //d배열에 그칸부터 m칸까지의 최대값 저장 for (int i = 0; i < n; i++) { for (int j = 0; j < n - m + 1; j++) { d[i][j] = getMaxPrice(i, j); } } //i,j를 선택한 상태에서 찾을수 있는 나머지에 대해 //비교하여 최대값 찾는다. int res = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < n - m + 1; j++) { res = max(res, dfs(i, j)+d[i][j]); } } printf("#%d %d\n", tc, res); } } | cs |
'SWEA::문제풀이' 카테고리의 다른 글
1949 등산로 조성 (0) | 2018.02.13 |
---|---|
2477 차량 정비소 (0) | 2018.02.07 |
1249 보급로 (0) | 2018.01.25 |
1953 탈주범 검거 (0) | 2018.01.23 |
2105 디저트 카페 (0) | 2018.01.21 |