반응형
https://www.acmicpc.net/problem/1799
1799번: 비숍
첫째 줄에 체스판의 크기가 주어진다. 체스판의 크기는 10이하의 자연수이다. 둘째 줄부터 아래의 예와 같이 체스판의 각 칸에 비숍을 놓을 수 있는지 없는지에 대한 정보가 체스판 한 줄 단위로
www.acmicpc.net
[ 문제풀이 ]
10초라는 시간제한 때문에 얼핏 보면 쉬워 보이는 문제이지만 10x10의 체스판을 모두 체크한다면 O(2^(100))이므로 10초라는 시간도 매우 부족합니다.
따라서 비숍의 특성을 이용하여 시간을 많이 줄여야합니다. 비숍은 체스판에서 서로 다른 색 위치에 있으면 서로 공격할 수 없습니다.
왜냐하면 처음 검정색 위치에 서 있던 비숍은 검은색 위만을 움직일 수 있고, 반대로 흰색 위에 있던 비숍은 흰색 위만을 움직일 수 있기 때문입니다.
이러한 특성을 이용하면 검은색은 검은색끼리 흰색은 흰색끼리 계산하여 O(2^(50)*2^(50))의 시간 복잡도를 가지게 되므로 10초 안에 충분히 풀 수 있습니다.
[ 소스 코드 ]
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 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | #include <iostream> using namespace std; struct board { int num; int color = 0; }; int N; board arr[11][11]; int dy[4] = { -1,-1,1,1 }; int dx[4] = { -1,1,-1,1 }; int ansW; int ansB; int check(int y, int x) //비숍을 놓을 수 있으면 1 리턴 없으면 0 리턴 { for (int i = 0; i < 4; i++) { for (int j = 1; j < N; j++) { int yy = y + dy[i] * j; int xx = x + dx[i] * j; if (yy >= 0 && yy < N && xx >= 0 && xx < N) { if (arr[yy][xx].num == 2) { return 0; } } } } return 1; } void dfsW(int y, int x) //체스판의 흰색 부분 { int flag = 0; while ((arr[y][x].num != 1 || arr[y][x].color != 0) && y<N) { x++; //체스말을 놓을 수 있을 때 까지 x++ if (x == N) { y++; x = 0; } } if (y == N) { int cnt = 0; for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { if (arr[i][j].num == 2) { cnt++; } } } if (ansW < cnt) { ansW = cnt; } return; } if (check(y, x)) { //비숍을 놓을 수 있는지 없는지 체크 후 arr[y][x].num = 2; //말을 놓거나 } else { flag = 1; //놓지 못한다고 체크 } int nx = x + 1; int ny = y; if (nx == N) { nx = 0; ny++; } dfsW(ny, nx); if (flag != 1) { //비숍을 놓은 상황이라면 arr[y][x].num = 1; //원상복구 } else { return; //아니라면 같은 상황을 겪게 되므로 return } dfsW(ny, nx); } void dfsB(int y, int x) //체스판의 검은색 부분 { int flag = 0; while ((arr[y][x].num != 1 || arr[y][x].color != 1) && y < N) { x++; if (x == N) { y++; x = 0; } } if (y == N) { int cnt = 0; for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { if (arr[i][j].num == 2) { cnt++; } } } if (ansB < cnt) { ansB = cnt; } return; } if (check(y, x)) { arr[y][x].num = 2; } else { flag = 1; } int nx = x + 1; int ny = y; if (nx == N) { nx = 0; ny++; } dfsB(ny, nx); if (flag != 1) { arr[y][x].num = 1; } else { return; } dfsB(ny, nx); } int main() { cin >> N; for (int i = 0; i < N; i++) { for (int j = 0;j < N; j++) { cin >> arr[i][j].num; if (i % 2 == 0) { //체스판의 검은색 부분을 1로 경신 if (j % 2 == 1) { arr[i][j].color = 1; } } else { if (j % 2 == 0) { arr[i][j].color = 1; } } } } dfsW(0, 0); dfsB(0, 1); cout << ansW+ansB; } | cs |
반응형
'백준' 카테고리의 다른 글
[ 백준 ] 15686번 - 치킨 배달 (C++) (0) | 2022.06.01 |
---|---|
[ 백준 ] 1149번 - RGB거리 (C++) (0) | 2022.05.31 |
[ 백준 ] 1562번 - 계단 수 (C++) (0) | 2022.05.29 |
[ 백준 ] 10844번 - 쉬운 계단 수 (C++) (0) | 2022.05.28 |
[ 백준 ] 2407번 - 조합 (C++) (0) | 2022.05.27 |