Home G3109. 빵집
Post
Cancel

G3109. 빵집

문제

image


제출 코드

image


  • 변경 전) 문제 접근 방식이 잘못되어서 처음에 복잡하게 코드를 짰다

    • 어느 열부터 파이프를 연결하냐에 따라 결과가 달라진다고 생각하여, 순열로 파이프 연결 시작할 행의 순서를 정한 뒤 백트래킹으로 연결되도록 했다
    • 백트래킹 과정에서 가봤던 길 표시하는 칸도 따로 만들어 둠
    • 1차 코드

      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
      71
      72
      
      package gold;
      
      import java.io.BufferedReader;
      import java.io.IOException;
      import java.io.InputStreamReader;
      
      public class G3109_bakery {
      
      	static int R, C;
      	static int max;
      	static char[][] arr;
      	static boolean[][] isPipe;
      	static boolean[] selected;
      	static int[] list;
      	static int result = Integer.MIN_VALUE;
      
      	public static void main(String[] args) throws IOException {
      		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
      
      		String[] line = br.readLine().split(" ");
      		R = Integer.parseInt(line[0]);
      		C = Integer.parseInt(line[1]);
      
      		arr = new char[R][C];
      		for(int i=0; i<R; i++) {
      			arr[i] = br.readLine().toCharArray();
      		}
      
      		max = 0;
      		isPipe = new boolean[R][C];
      		selected = new boolean[R];
      		list = new int[R];
      
      		perm(0);
      
      		System.out.println(result);
      	}
      
      	static void perm(int n) {
      		if(n==R) {
      			max = 0;
      			pipe(list[0], 0, 0);
      			result = Math.max(result, max);
      			return;
      		}
      
      		for(int i=0; i<R; i++) {
      			if(selected[i]) continue;
      			list[n] = i;
      			selected[i] = true;
      			perm(n+1);
      			selected[i] = false;
      
      		}
      	}
      
      	static void pipe(int r, int c, int idx) {	//list[i] = r값
      		if(r<0 || r>R-1 || arr[r][c] == 'x' || isPipe[r][c]) return;
      		else if(c>=C-1) {
      			max++;
      			if(++idx < R) pipe(list[idx], 0, idx);
      			return;
      		}
      
      		isPipe[r][c] = true;
      		pipe(r, c+1, idx);
      		pipe(r-1, c+1, idx);
      		pipe(r+1, c+1, idx);
      //		isPipe[r][c] = false;	//어차피 지금 안된 것들은 나중에 밟아도 안됨. 그러니 true놔둬서 다시 못밟게 하기
      								//그래서 이 문제는 사실 따로 배열 안만들고 원본배열 훼손해도 됨
      	}
      }
      


  • 변경 후) 다른 문제를 풀고와서 보니 저번에 설명을 듣고 이해 안된 부분이 이해되었다

    • 다음 열로 나아가는 순서를 가장 위부터 탐색해서 최대한 파이프를 높게 연결하면, 행의 순서는 따로 고려하지 않고 가장 위의 행부터 파이프를 만들어주면 최대 값이 나온다
    • 이미 거쳐간 칸은 파이프가 연결되어 있거나, 더 나아가도 파이프를 연결할 수 없는 칸이기에, 파이프 탐색 과정에서 원본배열에 그냥 표시하면 됨. ⇒ 따로 배열을 만들 필요가 없었다
    • 2차 코드

      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
      
      package gold;
      
      import java.io.BufferedReader;
      import java.io.IOException;
      import java.io.InputStreamReader;
      
      public class G3109_bakery {
      
      	static int R, C;
      	static int max = 0;
      	static boolean back;
      	static char[][] arr;
      
      	public static void main(String[] args) throws IOException {
      		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
      
      		String[] line = br.readLine().split(" ");
      		R = Integer.parseInt(line[0]);
      		C = Integer.parseInt(line[1]);
      
      		arr = new char[R][C];
      		for(int i=0; i<R; i++) {
      			arr[i] = br.readLine().toCharArray();
      		}
      
      		for(int i=0; i<R; i++) {
      			back = false;
      			pipe(i, 0);
      		}
      		System.out.println(max);
      	}
      
      	/* 주어진 현재 위치에서 이어질 수 있는 위치로 파이프 연결
      	 * - r : 현재 열 번호
      	 * - c : 현재 행 번호
      	 */
      	static void pipe(int r, int c) {
      		if(back || r<0 || r>R-1 || arr[r][c] == 'x') return;
      		else if(c>=C-1) {
      			arr[r][c]='x';
      			max++;
      			back = true;
      			return;
      		}
      		pipe(r-1, c+1);
      		pipe(r, c+1);
      		pipe(r+1, c+1);
      
      		arr[r][c]='x';
      	}
      }
      
This post is licensed under CC BY 4.0 by the author.