[BOJ] 1941 소문난 칠공주

mingggkeee·2022년 3월 16일
0

1941 소문난 칠공주

난이도 : 골드 3
유형 : 조합, DFS, BFS, 백트래킹

https://www.acmicpc.net/problem/1941

문제

총 25명의 여학생들로 이루어진 여학생반은 5×5의 정사각형 격자 형태로 자리가 배치되었고, 얼마 지나지 않아 이다솜과 임도연이라는 두 학생이 두각을 나타내며 다른 학생들을 휘어잡기 시작했다. 곧 모든 여학생이 ‘이다솜파’와 ‘임도연파’의 두 파로 갈라지게 되었으며, 얼마 지나지 않아 ‘임도연파’가 세력을 확장시키며 ‘이다솜파’를 위협하기 시작했다.

위기의식을 느낀 ‘이다솜파’의 학생들은 과감히 현재의 체제를 포기하고, ‘소문난 칠공주’를 결성하는 것이 유일한 생존 수단임을 깨달았다. ‘소문난 칠공주’는 다음과 같은 규칙을 만족해야 한다.

  1. 이름이 이름인 만큼, 7명의 여학생들로 구성되어야 한다.
  2. 강한 결속력을 위해, 7명의 자리는 서로 가로나 세로로 반드시 인접해 있어야 한다.
  3. 화합과 번영을 위해, 반드시 ‘이다솜파’의 학생들로만 구성될 필요는 없다.
  4. 그러나 생존을 위해, ‘이다솜파’가 반드시 우위를 점해야 한다. 따라서 7명의 학생 중 ‘이다솜파’의 학생이 적어도 4명 이상은 반드시 포함되어 있어야 한다.

여학생반의 자리 배치도가 주어졌을 때, ‘소문난 칠공주’를 결성할 수 있는 모든 경우의 수를 구하는 프로그램을 작성하시오.

입력

'S'(이다‘솜’파의 학생을 나타냄) 또는 'Y'(임도‘연’파의 학생을 나타냄)을 값으로 갖는 5*5 행렬이 공백 없이 첫째 줄부터 다섯 줄에 걸쳐 주어진다.

출력

첫째 줄에 ‘소문난 칠공주’를 결성할 수 있는 모든 경우의 수를 출력한다.

풀이

처음엔 BFS로 인접한 7칸을 탐색하여 4가지 규칙을 만족하는지 여부를 따졌는데, T자형의 모임은 탐색하지 못한다는 것을 알았다.
맵의 크기가 5*5로 고정되어 있기때문에 25개의 인자중에 7개를 무작위로 뽑는 조합을 써도 되겠다는 생각을 했고, 7개의 조합을 만들어 이다솜파가 4개 이상인 경우에만 bfs탐색을 통해 이 7개가 서로 인접해있는지 여부를 따져주었다.

코드

import java.io.*;
import java.util.LinkedList;
import java.util.Queue;

/**
 * BOJ_1941_G3_소문난 칠공주
 * @author mingggkeee
 * 조합,DFS,BFS,백트래킹
 */

public class BOJ_1941 {
	
	static class Location {
		int r, c;

		Location(int r, int c) {
			this.r = r;
			this.c = c;
		}
		
	}
	
	static char[][] map;
	static boolean[] isVisited;
	static int answer;
	static int[][] dir = {{1,0},{-1,0},{0,1},{0,-1}};
	
	static void combi(int cnt, int start, int y) {
		if (cnt == 7) {
			if (bfs())
				answer++;
			return;
		} 
		
		for (int i = start; i < 25; i++) {
			if (map[i / 5][i % 5] == 'Y' && y + 1 < 4) {
				isVisited[i] = true;
				combi(cnt + 1, i + 1, y + 1);
				isVisited[i] = false;
			}
			if (map[i / 5][i % 5] == 'S') {
				isVisited[i] = true;
				combi(cnt + 1, i + 1, y);
				isVisited[i] = false;
			}
		}
		
	}

	
	static boolean bfs() {
		Queue<Location> queue = new LinkedList<>();
		boolean[][] check = new boolean[5][5];
		
		for(int i = 0; i<25; i++) {
			if(isVisited[i]) {
				check[i / 5][i % 5] = true;
				queue.offer(new Location(i / 5, i % 5));
				break;
			}
		}
		
		int count = 1;
		
		while(!queue.isEmpty()) {
			Location now = queue.poll();
			for(int i = 0; i<4; i++) {
				int nr = now.r + dir[i][0];
				int nc = now.c + dir[i][1];
				if(nr < 0 || nr >= 5 || nc < 0 || nc >= 5) continue;
				if(!isVisited[nr * 5 + nc] || check[nr][nc]) continue;
				check[nr][nc] = true;
				queue.offer(new Location(nr, nc));
				count++;
			}
		}
		
		if(count == 7)
			return true;

		return false;
	}

	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		map = new char[5][5];
		isVisited = new boolean[25];
		for (int i = 0; i < 5; i++) {
			String input = br.readLine();
			map[i] = input.toCharArray();
		}
		combi(0, 0, 0);
		System.out.println(answer);
	}
}
profile
만반잘부

0개의 댓글

관련 채용 정보