일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- OS
- 백준
- 다운로드
- 마름모
- Eclipse
- scheduler
- 맥
- SJF
- Server
- 이클립스
- 별찍기
- 2805
- 달팽이는올라가고싶다
- 톰캣
- 운영체제
- SWEA
- swexpert
- 스케줄러
- srt
- 그림판유저
- 톰캣다운로드
- CPU
- priority scheduling
- BOJ
- RR
- 농작물수확하기
- tomcat
- acmicpc
- FCFS
- 백준2869
- Today
- Total
그림판유저의 은밀한 개발
[BOJ] 백준 1799 - 비숍 본문
체스판이 주어졌을 때 비숍은 대각선에 있는 다른 비숍을 잡을 수 있다고 합니다
구해야하는 값은 비숍들이 서로를 잡을 수 없도록 하여 체스판 위에 최대로 놓을 수 있는 비숍의 개수를 구하는 문제입니다.
N-queen 처럼 백트래킹을 쓰면 쉽게 구현할 수 있을 것 같았지만,
만약 10 x 10 에서 모든 자리가 1로 채워져 모든 자리에 비숍을 놓을 수 있다고 하면 10초안에는 절대로 구할 수 없게됩니다.
따라서 백트래킹을 들어가기 전에 몇가지 경우를 나누어주어야 합니다.
먼저, 체스판을 보게되면 흰색과 검정색으로 나뉘어진 부분을 볼 수 있습니다. (위의 체스판이 아닌 아래의 체스판을 참고해야 합니다.)
검정색 판에 비숍이 놓이게 되면 아래와 같이 흰색 부분에 놓인 비숍은 대각선 위에 위치하지 않으며 따라서 절대 잡을 수 없게 됩니다.
따라서 먼저 나눌 수 있는 경우
1. 검정색 판에 놓이는 비숍과 흰색 판에 놓이는 비숍
또한, 0이 적힌 곳에는 비숍을 놓을 수 없으므로,
다음 1을 찾아서 가는 것보다 1인 부분의 좌표를 따로 저장해 배열을 만들어 저장해준 다음 해당 배열을 백트래킹하는 것이 효율적이라 판단했습니다.
2. 0인 부분을 제외한 1의 좌표를 따로 저장.
따라서 입력이
5
1 1 0 1 1
0 1 0 0 0
1 0 1 0 1
1 0 0 0 0
1 0 1 1 1
와 같이 주어지는 경우,
검정색 판의 1의 좌표의 배열은 {(0,0), (0,4), (1, 1), (2,0), (2, 2), (2, 4), ... }
흰색 판의 1의 좌표의 배열은 {(0,1), (0, 3), (3, 0), ... } 이 됩니다.
즉, 검정색 판은 N(i,j) 에서 i+j%2 == 0 일 때, 흰색 판은 (i+j)%2 == 0 일 때가 됩니다.
위의 경우를 나누어 백트래킹을 진행한 코드는 다음과 같습니다.
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 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | import java.util.ArrayList; import java.util.Scanner; /* * 체스판이 다음과 같다고 하면, * | * * * * * | * * * * * | * * * * * | * * * * * 대각선에 올 수 없다는 뜻은 다음과 같다. * | * * | * * * | * * | * * * | * * | * * * | * * | * * * 왼쪽 칸에 있는 비숍들은 오른쪽 칸의 비숍과 대각선 관계에 없다. * 마찬가지로, 오른쪽 칸에 있는 비숍들은 왼쪽 칸의 비숍과 대각선 관계에 없다. * 즉, 왼쪽 칸에서의 최대 비숍과 오른쪽 칸의 최대 비숍의 수를 더하면 최대의 비숍의 수가 된다. */ public class Main { static int lAns = 0; static int rAns = 0; public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); ArrayList<int[]> lMap = new ArrayList<int[]>(); // 대각선에서 나올 수 있는 판 ArrayList<int[]> rMap = new ArrayList<int[]>(); for(int i=0; i<n; i++) { for(int j=0; j<n; j++) { int can = sc.nextInt(); if(can == 1) { int[] input = {i, j}; if((i+j)%2 == 0) // 왼쪽 맵의 비숍 lMap.add(input); else rMap.add(input); } } } boolean[] lvisit = new boolean[lMap.size()]; boolean[] rvisit = new boolean[rMap.size()]; lbfs(lMap, lvisit, 0, 0); rbfs(rMap, rvisit, 0, 0); System.out.println(rAns + lAns); } private static void lbfs(ArrayList<int[]> map, boolean[] visit, int n, int cnt) { // TODO Auto-generated method stub if(n >= map.size()) { lAns = lAns < cnt ? cnt : lAns; return; } if(cnt + (map.size() - n + 1) < lAns) return; for(int i=n; i<map.size(); i++) { if(isNotDiagonal(map, visit, i)) { visit[i] = true; lbfs(map, visit, i+1, cnt+1); visit[i] = false; } } lAns = lAns < cnt ? cnt : lAns; } private static void rbfs(ArrayList<int[]> map, boolean[] visit, int n, int cnt) { // TODO Auto-generated method stub if(n >= map.size()) { rAns = rAns < cnt ? cnt : rAns; return; } if(cnt + (map.size() - n + 1) < rAns) return; for(int i=n; i<map.size(); i++) { if(isNotDiagonal(map, visit, i)) { visit[i] = true; rbfs(map, visit, i+1, cnt+1); visit[i] = false; } } rAns = rAns < cnt ? cnt : rAns; } private static boolean isNotDiagonal(ArrayList<int[]> map, boolean[] visit, int n) { int[] a = map.get(n); for(int i=0; i<n; i++) { if(visit[i]) { int[] b = map.get(i); if(Math.abs(a[0] - b[0]) == Math.abs(a[1] - b[1])) { // 대각선에 있는 경우. return false; } } } return true; } } | cs |
'알고리즘 > acmicpc[백준]' 카테고리의 다른 글
[BOJ] 백준 2573 - 빙산 (0) | 2019.03.07 |
---|---|
[BOJ] 백준 2869 - 달팽이는 올라가고 싶다 (1) | 2019.03.07 |
[BOJ] 백준 10216 - Count Circle Groups (0) | 2019.03.07 |
[BOJ] 백준 5557 - 1학년 (0) | 2019.03.06 |