[알고리즘 문제해결 전략]6장. 무식하게 풀기_④
2018. 12. 29. 23:29ㆍAlgorithm/알고리즘 문제해결 전략
BOARDCOVER in algospot
problem
Thinking
우리가 보드판에 놓을 수 있는 블록의 모양은 다음과 같다.
[그림 1] 퍼즐 유형
이를 주어진 보드판에 채워넣는 방법에 대하여 고민을 해보면, 아래와 같이 대입이 가능하다.
[그림 2] 보드 예시
그러면 [그림 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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | int board[board_size][board_size]; int covers[4][3][2] = { {{0,0},{0,1},{1,0}}, {{0,0},{0,1},{1,1}}, {{0,0},{1,0},{1,1}}, {{0,0},{1,-1},{1,0}} }; int setting(int i_flag, int j_flag, int type,int flag) {//선택할 퍼즐의 모양을 나타내기 위해 type을 사용한다. int tmp_i, tmp_j; //그리고 퍼즐을 놓을지 아니면 제거할지 flag로 선택한다. int cover_flag = 0; for (int i = 0; i < 3; i++) { tmp_i = i_flag + covers[type][i][0]; tmp_j = j_flag + covers[type][i][1]; if (tmp_i >= 0 && tmp_i < H && tmp_j >= 0 && tmp_j < W) { if (flag == set) { if (board[tmp_i][tmp_j] == empty) cover_flag++;//모든 곳에 놓을 수 있으면 cover_flag = 3이 된다. else { return 0;//퍼즐을 놓을 수 없으므로 0(false)를 반환한다. } } else if (flag == del) { if (board[tmp_i][tmp_j] == covered) cover_flag++;//제거할 퍼즐이 있으면 cover_flag = 3이 된다. else { return 0;//퍼즐을 제거할 수 없으므로 0(false)를 반환한다. } } } else { return 0;//퍼즐이 보드를 벗어나면 퍼즐을 놓거나 제거할 수 없다 false 반환 } } if (cover_flag == 3) {//퍼즐을 놓거나 제거한다. for (int i = 0; i < 3; i++) { tmp_i = i_flag + covers[type][i][0]; tmp_j = j_flag + covers[type][i][1]; if (flag == set) { board[tmp_i][tmp_j] = covered; } else if (flag == del) { board[tmp_i][tmp_j] = empty; } } } return 1; } void cover_block() { int i_flag,j_flag; i_flag = j_flag = -1; for (int i = 0; i < H; i++) { for (int j = 0; j < W; j++) { if (board[i][j] == empty) {//보드에서 제일 위,왼쪽에서 빈부분을 탐색한다. i_flag = i; j_flag = j; break; } } if (i_flag != -1) break; } if (i_flag == -1) {//빈곳이 없으면 다 채워 진것이므로 한개의 case가 완성된 것이다. ans++; return; } for (int i = 0; i < 4; i++) { if (setting(i_flag, j_flag, i, set) == 1) {//퍼즐 ㅏ나를 놓을 수 있으면 퍼즐을 놓고 cover_block();//다시 재귀함수로 퍼즐을 새로 셋팅된 보드에서 다시 퍼즐을 놓는 것을 시도한다. setting(i_flag, j_flag, i, del);// 다른 퍼즐을 놓기위해 놓았던 퍼즐을 제거한다. } } } | cs |
여기서 시행시간을 좀 더 줄이는 팁은 우리가 놓을 수 있는 퍼즐은 3의 크기의 퍼즐이므로 빈곳이 3의 배수가 아닌경우 퍼즐을 채울 수 없으므로 미리 걸러 준다.
Solve
출처
문제: algosport BOARDCOVER문제( 링크 )
'Algorithm > 알고리즘 문제해결 전략' 카테고리의 다른 글
[알고리즘 문제해결 전략]6장. 무식하게 풀기_⑤ (0) | 2018.12.30 |
---|---|
[알고리즘 문제해결 전략]6장. 무식하게 풀기_③ (0) | 2018.12.29 |
[알고리즘 문제해결 전략]6장. 무식하게 풀기_② (0) | 2018.12.29 |
[알고리즘 문제해결 전략]6장. 무식하게 풀기_① (0) | 2018.12.28 |
[알고리즘 문제해결 전략]5장. 알고리즘의 정당성 증명 (0) | 2018.12.27 |