BOJ 1012) 유기농 배추
- [ 기타 ]/백준, 프로그래머스
- 2021. 12. 27.
문제
차세대 영농인 한나는 강원도 고랭지에서 유기농 배추를 재배하기로 하였다. 농약을 쓰지 않고 배추를 재배하려면 배추를 해충으로부터 보호하는 것이 중요하기 때문에, 한나는 해충 방지에 효과적인 배추흰지렁이를 구입하기로 결심한다. 이 지렁이는 배추근처에 서식하며 해충을 잡아 먹음으로써 배추를 보호한다. 특히, 어떤 배추에 배추흰지렁이가 한 마리라도 살고 있으면 이 지렁이는 인접한 다른 배추로 이동할 수 있어, 그 배추들 역시 해충으로부터 보호받을 수 있다. 한 배추의 상하좌우 네 방향에 다른 배추가 위치한 경우에 서로 인접해있는 것이다.
한나가 배추를 재배하는 땅은 고르지 못해서 배추를 군데군데 심어 놓았다. 배추들이 모여있는 곳에는 배추흰지렁이가 한 마리만 있으면 되므로 서로 인접해있는 배추들이 몇 군데에 퍼져있는지 조사하면 총 몇 마리의 지렁이가 필요한지 알 수 있다. 예를 들어 배추밭이 아래와 같이 구성되어 있으면 최소 5마리의 배추흰지렁이가 필요하다. 0은 배추가 심어져 있지 않은 땅이고, 1은 배추가 심어져 있는 땅을 나타낸다.
전개
값이 1인 각 좌표별로 상하좌우 네 방향의 좌표를 검사하여 1이면 2로 바꾸어주는 함수를 DFS로 재귀적으로 짜면 되겠다고 생각함
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Main practice = new Main();
Scanner sc = new Scanner(System.in);
int T = sc.nextInt();
for(int k=0; k<T; k++) {
int M = sc.nextInt(); //가로길이
int N = sc.nextInt(); //세로길이
int K = sc.nextInt();
int cnt = 0;
int[][] arr = new int[M][N];
for (int i = 0; i < K; i++) {
int m = sc.nextInt();
int n = sc.nextInt();
arr[m][n] = 1;
}
for (int i = 0; i < M; i++) {
for (int j = 0; j < N; j++) {
if (arr[i][j] == 1) {
cnt++;
setNeighbor(arr, i, j, M, N);
}
}
}
System.out.println(cnt);
}
}
// 상하좌우 4개의 좌표를 검사
private static void setNeighbor(int[][] arr, int i, int j, int M, int N) {
if(arr[i][j] == 1) {
// 1이라면 2로 바꾸어주기(체크한것)
arr[i][j] = 2;
if (i > 0)
setNeighbor(arr, i - 1, j, M, N);
if (j > 0)
setNeighbor(arr, i, j - 1, M, N);
if (i < M-1)
setNeighbor(arr, i + 1, j, M, N);
if (j < N-1)
setNeighbor(arr, i, j + 1, M, N);
}
}
}
https://www.acmicpc.net/problem/1012
#include <stdio.h>
int n, m, k, tb[100][100], tt;
void f(int x, int y)
{
tb[x][y] = 2;
if (x + 1 <= n && tb[x + 1][y] == 1)f(x + 1, y);
if (x - 1 >= 0 && tb[x - 1][y] == 1)f(x - 1, y);
if (y + 1 <= m && tb[x][y + 1] == 1)f(x, y + 1);
if (y - 1 >= 0 && tb[x][y - 1] == 1)f(x, y - 1);
}
int main()
{
int i, j, a, b, cnt;
scanf("%d", &tt);
while (tt--)
{
cnt = 0;
scanf("%d %d %d", &n, &m, &k);
for (i = 0; i <= n; i++)for (j = 0; j <= m; j++)tb[i][j] = 0;
for (i = 0; i < k; i++)
{
scanf("%d %d", &a, &b);
tb[a][b] = 1;
}
for (i = 0; i <= n; i++)for (j = 0; j <= m; j++)if (tb[i][j] == 1)f(i, j), cnt++;
printf("%d\n", cnt);
}
}
추가로 생각해볼만한것
유망함수 추가여부
👍 백트래킹 기법의 유망성 판단
어떤 노드의 유망성, 즉 해가 될 만한지 판단한 후 유망하지 않다고 결정되면 그 노드의 이전(부모)로 돌아가(Backtracking) 다음 자식 노드로 갑니다.
해가 될 가능성이 있으면 유망하다(promising)고 하며, 유망하지 않은 노드에 가지 않는 것을 가지치기(pruning) 한다고 하는 것입니다.
실제로 branching하기전에 promising여부를 검사하여 유망성을 판단함으로서 실행시간을 줄이는 방법이 있는데
이 문제의 경우 인접한 좌표가 1값이라면 무조건 유망하다고 생각하여 유망함수를 추가하지 않았다.
(+검사하려면 상하좌우에 1값을 가지는 좌표가 있는지 검사해야되는데 이것은 setNeighbor함수의 실행과정과 동일하므로 실행시간의 이득이 발생하지 않는다)
'[ 기타 ] > 백준, 프로그래머스' 카테고리의 다른 글
BOJ 2580) 스도쿠 (0) | 2022.01.14 |
---|---|
BOJ 2156) 포도주 시식 (0) | 2022.01.03 |
BOJ 15649) N과 M(1) (0) | 2021.12.30 |
BOJ 1018) 체스판 다시 칠하기 (0) | 2021.12.29 |
BOJ 1699) 제곱수의 합 (0) | 2021.12.20 |