문제 : https://www.acmicpc.net/problem/1760

 

 

[ 문제 요약 ]

  • 룩은 격자판의 같은 행, 열에 다른 룩이 있다면 공격할 수 있습니다. 여기에 벽과 구덩이를 도입합니다. 구덩이와 벽에는 룩을 놓을 수 없습니다.
  • 벽을 사이에 두고 있는 두 록은 서로 공격이 불가하지만 구덩이는 서로 공격할 수 있습니다. 격자판 모양이 주어질 때, 서로 공격하지 않게 록을 가장 많이 배치할 때의 록수를 출력합니다.

 

[ 테스트 케이스 설명 ]

3 4	// 격자 크기 행Y,열X(1<=100)가 주어짐
2 0 0 0
2 2 2 1
0 1 0 2// 0은 빈격자, 1은 구덩이, 2는 벽
첫째 줄에 배치할 수 있는 Rook의 최대 개수를 출력, 답 : (2)
힌트 : 12열과 33열에 하나씩, 총 두 개의 Rook을 배치할 수 있다.

 

 

[ 알고리즘 분류 ]

  • 이분 매칭

 

[ 문제 해설 ]

https://kyjdummy.tistory.com/100

 

BOJ 백준 9525 룩 배치하기

문제 : https://www.acmicpc.net/problem/9525 [ 문제 요약 ]N*N의 체스판이 주어지고, 빈칸과 가로막는 벽이 주어질 때, 가로, 세로를 직선으로 갈 수 있는 '록'을 최대 몇 개를 배치할 수 있는지를 출력합니

kyjdummy.tistory.com

 

위 문제에서 구멍만 추가된 것입니다. 구멍은 룩은 놓을 수 없지만, 공격은 가능하므로, 구멍일 때는 인덱스를 그대로 유지해 주는 방식으로 구현하면 문제를 풀 수 있습니다. 이 문제를 풀기 전에 위 문제를 먼저 푸는 것을 추천드립니다.

 

[ 정답 코드 ]

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

class Main{
	
	static final int MAX = 100 * 100;
	static int time;
	static int match[];
	static int visitTime[];
	static List<Integer> adList[];
	
	public static void main(String[] args)throws Exception{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		int Y = Integer.parseInt(st.nextToken());// 격자 크기 행Y(1<=100)가 주어짐
		int X = Integer.parseInt(st.nextToken());// 격자 크기 열X(1<=100)가 주어짐
		int map[][] = new int[Y + 1][X + 1];
		int yIdx[][] = new int[Y + 1][X + 1];
		int xIdx[][] = new int[Y + 1][X + 1];
		int yValue = 0;
		int xValue = 0;
		
		adList = new ArrayList[MAX + 1];
		for(int i=0; i<adList.length; i++)
			adList[i] = new ArrayList<>();
		
		for(int y=1; y<=Y; y++)
		{
			st = new StringTokenizer(br.readLine());
			for(int x=1; x<=X; x++)
			{
				map[y][x] = Integer.parseInt(st.nextToken());
				// 0은 빈격자, 1은 구덩이, 2는 벽
				if(map[y][x] == 0)// 빈 격자인 경우
				{
					yIdx[y][x] = yIdx[y-1][x] == 0 ? ++yValue : yIdx[y-1][x];
					xIdx[y][x] = xIdx[y][x-1] == 0 ? ++xValue : xIdx[y][x-1];
					adList[yIdx[y][x]].add(xIdx[y][x]);
				}
				// 구덩이인 경우, 인덱스를 그대로 복사해서 갖고와야 다음연산이 가능하다.
				else if(map[y][x] == 1)
				{
					yIdx[y][x] = yIdx[y-1][x];
					xIdx[y][x] = xIdx[y][x-1];
				}
			}
		}
		
		match = new int[xValue + 1];
		visitTime = new int[xValue + 1];
		int cnt = 0;
		for(int y=1; y<=yValue; y++)
		{
			++time;
			if(dfs(y))
				++cnt;
		}
		System.out.print(cnt);
	}
	static boolean dfs(int y) {
		for(int x : adList[y])
		{
			if(visitTime[x] == time)
				continue;
			
			visitTime[x] = time;
			if(match[x] == 0 || dfs(match[x]))
			{
				match[x] = y;
				return true;
			}
		}
		return false;
	}
}

'알고리즘 > 이분 매칭' 카테고리의 다른 글

BOJ 백준 11670 초등 수학  (0) 2025.05.30
BOJ 백준 2787 흔한 수열 문제  (0) 2025.05.30
BOJ 백준 9577 토렌트  (0) 2025.05.29
BOJ 백준 1574 룩 어택  (0) 2025.05.28
BOJ 백준 9525 룩 배치하기  (0) 2025.05.28

+ Recent posts