https://www.acmicpc.net/problem/14391
14391번: 종이 조각
영선이는 숫자가 쓰여 있는 직사각형 종이를 가지고 있다. 종이는 1×1 크기의 정사각형 칸으로 나누어져 있고, 숫자는 각 칸에 하나씩 쓰여 있다. 행은 위에서부터 아래까지 번호가 매겨져 있고,
www.acmicpc.net
코드설명
완전탐색(BruteForce) + DFS(깊이우선탐색) 문제입니다.
문제에서 가장 중요한점은, 완전탐색을 통해서 각 종이조각을 가로로 나눌지, 세로로 나눌지 모두 정하는 것 입니다.
종이조각을 나누는 완전탐색 코드입니다.
- 사실 0으로 다시 초기화시켜주는 부분은 다음 함수 전에 이미 초기화되어서 상관없지만 추가해주었습니다.
public static void simulate(int level, int r, int c) { if(c >= M) { r = r + 1; c = 0; } if(r >= N) { caclulate(); return ; } combination[r][c] = ROW; simulate(level + 1, r, c + 1); combination[r][c] = 0; combination[r][c] = COL; simulate(level + 1, r, c + 1); combination[r][c] = 0; }
그리고 모든 종이조각을 나누었다면, 연산작업을 진행하면 됩니다.
visited[][] 로 가로, 세로 계산을 나누어서 진행해야하는 문제입니다.
만약 visited[i][j] = true 로 이루어져있다면, 해당 부분은 가로로 처리합니다.
만약 visited[i][j] = false 로 이루어져있다면, 해당 부분은 세로로 처리합니다.
헷갈리는 부분은, '행'을 기준으로 DFS 함수를 짯기떄문
DFS로써 종료조건을 잘 설정해야합니다.
종료조건은 행이 == N 이 되면 전체 계산을 종료한다는점
추가적인 조건 은 열이 >= M 이 되면 다음 열로 넘어가야한다는점 입니다. 또한 이미 col >= M 인 상태이기에 중지시켜줘야 col이 ArrayoutofIndex Exception이 나오지 않습니다.
전체 가로 계산을 하는 과정은 true, 즉 가로 일경우 연속적으로 더하기 처리해줍니다.
세로도 마찬가지입니다.
코드
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.StringTokenizer; public class Main { public static int N,M, K; public static int[][] map; public static int[][] combination; //가로라면 TRUE, 세로라면 FALSE입니다. public static int ROW = 1, COL = 2; public static int answer = 0; public static void main(String[] args) throws IOException{ BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st = new StringTokenizer(br.readLine()); N = Integer.parseInt(st.nextToken()); M = Integer.parseInt(st.nextToken()); map = new int[N][M]; combination = new int[N][M]; for(int i=0;i<N;i++) { st = new StringTokenizer(br.readLine()); String str = st.nextToken(); for(int j=0;j<M;j++) { map[i][j] = str.charAt(j) - '0'; } } simulate(0, 0, 0); System.out.println(answer); } public static void simulate(int level, int r, int c) { if(c >= M) { r = r + 1; c = 0; } if(r >= N) { caclulate(); return ; } combination[r][c] = ROW; simulate(level + 1, r, c + 1); combination[r][c] = 0; combination[r][c] = COL; simulate(level + 1, r, c + 1); combination[r][c] = 0; } public static void caclulate() { boolean[][] visited = new boolean[N][M]; int wholeSum = 0; //combination 배열을 돌면서 만약 가로일시 가능한 가로까지 모두 이동, 세로일시 가능한 세로까지 모두 이동합니다. for(int i=0;i<N;i++) { for(int j=0;j<M;j++) { if(visited[i][j] == true) continue; //이미 방문한곳은 방문하지 않습니다. if(combination[i][j] == COL) { int sum = map[i][j]; visited[i][j] = true; int startCol = j + 1; while(startCol < M && combination[i][startCol] == COL && visited[i][startCol] == false) { sum = sum * 10 + map[i][startCol]; visited[i][startCol] = true; startCol ++; } wholeSum += sum; } else if(combination[i][j] == ROW) { int sum = map[i][j]; visited[i][j] = true; int startRow = i + 1; while(startRow < N && combination[startRow][j] == ROW && visited[startRow][j] == false) { sum = sum * 10 + map[startRow][j]; visited[startRow][j] = true; startRow ++; } wholeSum += sum; } } } answer = Math.max(answer, wholeSum); } }
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.*; public class Main { public static int N,M; public static int[][] map; public static boolean[][] visited; //방문처리 public static int answer = Integer.MIN_VALUE; public static void main(String[] args) throws IOException{ BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st = new StringTokenizer(br.readLine()); N = Integer.parseInt(st.nextToken()); M = Integer.parseInt(st.nextToken()); map = new int[N][M]; visited = new boolean[N][M]; for(int i=0;i<N;i++) { String str = br.readLine(); for(int j=0;j<M;j++) { map[i][j] = str.charAt(j) - '0'; } } simulate(0, 0); System.out.println(answer); } public static void simulate(int row, int col) { //행이 N과 같아지면, 탐색이 끝난것 if(row == N) { calculate(); return ; } //열 넘어가면 해당 로직처리 if(col >= M) { simulate(row + 1, 0); return ; //가로 계산이 끝나면 종료시켜야함. } //가로라면 true처리 visited[row][col] = true; simulate(row, col + 1); //가로 방문안한경우도 처리 ( 이경우 세로로 사용됨 ) visited[row][col] = false; simulate(row, col + 1); } public static void calculate() { int result = 0; int sumTemp = 0; //가로 계산 for(int i=0;i<N;i++) { sumTemp = 0; for(int j=0;j<M;j++) { if(visited[i][j] == true) { sumTemp *= 10; sumTemp += map[i][j]; }else { result += sumTemp; sumTemp = 0; } } //행 한줄 계산 끝날때마다 result에 + 연산 추가 result += sumTemp; } for(int i=0;i<M;i++) { sumTemp = 0; for(int j=0;j<N;j++) { if(visited[j][i] == false) { sumTemp *= 10; sumTemp += map[j][i]; }else { result += sumTemp; sumTemp = 0; } } result += sumTemp; } answer = Math.max(answer, result); } }
'알고리즘 > 백준' 카테고리의 다른 글
[백준] 14916 거스름돈 - DP JAVA (0) | 2023.07.20 |
---|---|
[백준] 1789 수들의 합 - 수학 JAVA (0) | 2023.07.19 |
[백준] 16637 괄호 추가하기 - 완전탐색(BruteForce) + DFS(깊이우선탐색) + 연산자 JAVA (0) | 2023.07.18 |
[백준] 21278 호석이 두 마리 치킨 - DFS(조합) + BFS JAVA (0) | 2023.07.17 |
[백준] 1025 제곱수 찾기 - 완전탐색 + 아이디어 JAVA (0) | 2023.07.17 |