SWEA 2115 - 벌꿀채취
Updated:
Java
2115 번 - 벌꿀채취
문제
벌통들의 크기 N과 벌통에 있는 꿀의 양에 대한 정보, 선택할 수 있는 벌통의 개수 M, 꿀을 채취할 수 있는 최대 양 C가 주어진다.
이때 두 일꾼이 꿀을 채취하여 얻을 수 있는 수익의 합이 최대가 되는 경우를 찾고, 그 때의 최대 수익을 출력하는 프로그램을 작성하라.
접근 방법
처음 풀었을 때는, 조금 단순하게 접근하였다.
첫 번째 꿀벌의 위치 y, x / 두 번째 꿀벌의 위치 y, x를 지정해주는 4중 for문으로 각 위치를 정해준다.
두 꿀벌의 위치에서 각각 m개만큼 연속되게 꿀을 선택한다.
만약 선택한 꿀의 합이 c 이상이면, DFS
를 사용하여 m개중 c를 넘지 않는 한 제일 많은 양의 꿀을 선택하게한다.
구한 꿀의 양 중 최대 값을 갱신하여 해결하였다.
코드
import java.io.*;
import java.util.*;
class Solution {
static int result = 0, n, m, c;
static double maxHoney;
static int[][] beejar;
static int[] honeySel;
public static void main(String []args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer stk;
int tc = stoi(br.readLine());
for(int tidx = 1; tidx <= tc; tidx++) {
result = 0;
stk = new StringTokenizer(br.readLine());
n = stoi(stk.nextToken());
m = stoi(stk.nextToken());
c = stoi(stk.nextToken());
beejar = new int[n][n];
honeySel = new int[m];
for(int i = 0; i < n; i++) {
stk = new StringTokenizer(br.readLine());
for(int j = 0; j < n; j++) {
beejar[i][j] = stoi(stk.nextToken());
}
}
int firstHoney, honey= 0;
int firSum = 0, secSum = 0;
// 첫번째 일꾼 꿀 선택
for(int i1 = 0; i1 < n; i1++) {
for(int j1 = 0; j1 < n - m + 1; j1++) {
firstHoney = 0;
firSum = 0;
// 첫 번째 꿀벌이 m개 만큼 꿀을 선택한다.
for(int k = j1; k < m + j1; k++) {
firSum += beejar[i1][k];
firstHoney += Math.pow(beejar[i1][k], 2);
honeySel[k - j1] = beejar[i1][k];
}
// c보다 넘으면 c를 넘지 않는 한에서 꿀을 선택한다
if(firSum > c) {
maxHoney = 0;
DFS(0,0,0,0);
firstHoney = (int) maxHoney;
}
// 두번째 일꾼 꿀 선택
for(int i2 = i1; i2 < n; i2++) {
// 첫번째 일꾼과 두번째 일꾼이 같은 라인에 있으면
if(i1 == i2) {
for(int j2 = j1 + m; j2 < n - m + 1; j2++) {
honey = firstHoney;
// 두 번째 꿀벌이 m개 만큼 꿀을 선택한다.
for(int k = j2; k < m + j2; k++) {
secSum += beejar[i2][k];
honey += Math.pow(beejar[i2][k], 2);
honeySel[k - j2] = beejar[i2][k];
}
// 두 번째 꿀벌이 선택한 꿀의 양이 c를 넘으면 c를 넘지 않는 한에서 꿀을 선택한다
if(secSum > c) {
maxHoney = 0;
DFS(0,0,0, firstHoney);
honey = (int) maxHoney;
}
result = Math.max(result, honey);
//System.out.println(i1 + " " + j1 + " " + i2 + " " + j2);
}
}
// 첫번째 일꾼과 두번째 일꾼이 다른 라인에 있으면
else {
for(int j2 = 0; j2 < n - m + 1; j2++) {
honey = firstHoney;
for(int k = j2; k < m + j2; k++) {
secSum += beejar[i2][k];
honey += Math.pow(beejar[i2][k], 2);
honeySel[k - j2] = beejar[i2][k];
}
if(secSum > c) {
maxHoney = 0;
DFS(0,0,0, firstHoney);
honey = (int) maxHoney;
}
result = Math.max(result, honey);
}
}
}
}
}
System.out.println("#" + tidx + " " + result);
}
}
// 선택한 m개의 꿀 중에서 c를 넘지 않는 한에서, 꿀들의 합이 제일 큰 것을 찾는다
static void DFS(int lv, int sum, int start, double powSum) {
if(lv == m) {
maxHoney = Math.max(powSum, maxHoney);
return;
}
for(int i = start; i < m; i++) {
if(sum + honeySel[i] <= c)
DFS(lv + 1, sum + honeySel[i], i + 1, powSum + Math.pow(honeySel[i], 2));
DFS(lv + 1, sum, i + 1, powSum);
}
}
static int stoi(String str) {
return Integer.parseInt(str);
}
}
총평
후기
1시간 정도 흘러가는 대로 짜다보니 맞은 문제.
for문으로 다루는건 실수를 하는 경우가 정말 많다.
개선할 점
4중 for문이 아닌, DFS를 사용하여 각 꿀벌의 위치를 정하도록 개선하자.