개인 공부/백준
18290번 NM과 K (1)
코딩하는 동훈
2024. 8. 17. 21:45
문제:
크기가 N×M인 격자판의 각 칸에 정수가 하나씩 들어있다. 이 격자판에서 칸 K개를 선택할 것이고, 선택한 칸에 들어있는 수를 모두 더한 값의 최댓값을 구하려고 한다. 단, 선택한 두 칸이 인접하면 안된다. r행 c열에 있는 칸을 (r, c)라고 했을 때, (r-1, c), (r+1, c), (r, c-1), (r, c+1)에 있는 칸이 인접한 칸이다.
입력:
첫째 줄에 N, M, K가 주어진다. 둘째 줄부터 N개의 줄에 격자판에 들어있는 수가 주어진다.
출력:
선택한 칸에 들어있는 수를 모두 더한 값의 최댓값을 출력한다.
접근 방법
- 브루트포스로 모든 가능성을 따지는게 좋아보임
- 백트래킹을 통해 K개를 선정해서 최대값을 비교하는 백트래킹을 구현
코드
접기/펼치기
import java.util.*;
public class NM과_K_1
{
static int n , m , k;
static int map[][];
static boolean checkMap[][];
static int maxValue = Integer.MIN_VALUE;
static int curValue =0;
public static void main(String [] args)
{
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
m = sc.nextInt();
k = sc.nextInt();
map = new int[n][m];
checkMap = new boolean [n][m];
for(int i = 0 ; i < n ; i ++)
{
for(int j = 0 ; j < m ; j ++)
{
map[i][j] = sc.nextInt();
}
}
for(int i = 0 ; i < n ; i++)
{
for(int j = 0 ; j < m ; j++)
{
findMax(i,j,1);
}
}
System.out.println(maxValue);
}
static int dx[] = {1,0,-1,0};
static int dy[] = {0,1,0,-1};
public static void findMax(int X,int Y,int t)
{
checkMap[X][Y] = true;
curValue += map[X][Y];
if(t == k)
{
if(maxValue < curValue) maxValue = curValue ;
}
else
{
for(int i = 0 ; i < n ; i ++)
{
for(int j = 0 ; j < m ; j++)
{
if(!checkMap[i][j]&&isValid(i,j))
{
findMax(i, j, t+1);
}
}
}}
curValue -= map[X][Y];
checkMap[X][Y] = false;
}
public static boolean isValid(int x , int y)
{
for(int i = 0 ; i < 4 ; i ++)
{
int nx = x + dx[i];
int ny = y + dy[i];
if(nx>=0 && ny >= 0 && nx < n && ny < m && checkMap[nx][ny])
{
return false;
}
}
return true;
}
}
처음에 백트래킹할 때 재귀를 거치면서 방문표시가 해제되면 안되는 상황에서 방문표시가 해제되어 버리는 경우가 발생했었다. 이 경우를 해결하기 위해 방문한 위치만 방문표시하는 로직으로 변경하였다.
지식이 늘었다.