반응형
문제 설명
algospot.com :: BLOCKGAME
블록 게임 문제 정보 문제 시티빌과 비주얼드에 지친 진호와 현환이는 집에 굴러다니는 블럭들을 모아 새로운 게임을 하기로 했습니다. 5×5 크기의 게임판에서 시작해, 둘이 번갈아 가며 블럭을
www.algospot.com
- 5x5크기의 게임판에서 진호와 현환이는 번갈아가며 하나씩 게임판에 블럭을 놓는다.
- 블럭은 3칸짜리 L모양 블럭과 2칸짜리 블럭이 있다.
- 블럭은 항상 게임판의 줄에 맞춰 놓아야 한다.
- 블럭은 자유롭게 뒤집거나 회전하기가 가능하다.
- 더 올려놓을 수 있는 블록이 없게 되면 마지막에 올려놓은 사람이 승리한다.
=> 진행 중인 게임판이 주어질 때, 이번 차례인 사람이 승리할 수 있는 방법이 있는지 출력하기
문제 풀이
문제 풀이
이 문제는 이기는 방법이 하나라도 있으면 WINNING을 출력할 수 있는 문제이다.
따라서, 블록이 놓여있지 않는 빈 칸을 만나면 해당 칸에 놓을 수 있는 블록의 경우의 수를 전부 수행하고
한 번이라도 이기는 경우가 있다면 연산을 더 수행할 필요 없이 승리함을 반환하면 된다.
메모이제이션
진행 중인 게임판 상황에 대한 결과를 저장하면 중복 계산이 발생했을 때 시간을 단축시킬 수 있다.
이 문제는 5x5로 게임판의 크기가 정해져 있다.
하지만 2차원 배열을 메모이제이션으로 저장하기엔 공간을 너무 많이 차지하므로
비트마스킹을 이용해서 5x5 = 25 각 칸에 한 칸씩에 대한 정보를 저장하도록 하면
1<<25크기의 배열에 메모이제이션을 수행하도록 할 수 있다.
문제 풀이 코드
#include <iostream>
#include <string.h>
using namespace std;
char memo[1 << 25]; // 1 << 25
int game(int map) {
char& ret = memo[map];
if (ret != -1)
return ret;
ret = 0;
// * 1
// 2 3 4
for (int i = 0; i < 25; ++i) {
if (((map >> i) & 1) == 1) {
int cpmap = map;
cpmap = cpmap ^ (1 << i);
bool one = i % 5 != 4 && ((map >> (i + 1)) & 1);
bool two = i < 20 && i % 5 != 0 && ((map >> (i + 4)) & 1);
bool three = i < 20 && ((map >> (i + 5)) & 1);
bool four = i < 19 && i % 5 != 4 && ((map >> (i + 6)) & 1);
if (one) {
cpmap = cpmap ^ (1 << (i + 1)); // 가로 2칸
if (three) { // 아래 1칸
cpmap = cpmap ^ (1 << (i + 5));
int result = game(cpmap);
if (!result)
return ret = 1;
cpmap = cpmap ^ (1 << (i + 5));
}
if (four) { // 아래 우측 대각선 1칸
cpmap = cpmap ^ (1 << (i + 6));
int result = game(cpmap);
if (!result)
return ret = 1;
cpmap = cpmap ^ (1 << (i + 6));
}
int result = game(cpmap);
if (!result)
return ret = 1;
cpmap = cpmap ^ (1 << (i + 1));
}
if (three) {
cpmap = cpmap ^ (1 << (i + 5)); // 세로 2칸
if (two) { // 아래 좌측 대각선 1칸
cpmap = cpmap ^ (1 << (i + 4));
int result = game(cpmap);
if (!result)
return ret = 1;
cpmap = cpmap ^ (1 << (i + 4));
}
if (four) { // 아래 우측 대각선 1칸
cpmap = cpmap ^ (1 << (i + 6));
int result = game(cpmap);
if (!result)
return ret = 1;
cpmap = cpmap ^ (1 << (i + 6));
}
int result = game(cpmap);
if (!result)
return ret = 1;
cpmap = cpmap ^ (1 << (i + 5));
}
cpmap = cpmap ^ (1 << i);
}
}
return ret;
}
int main() {
int C;
cin >> C;
memset(memo, -1, sizeof(memo));
for (int tc = 1; tc <= C; ++tc) {
int map = 0;
for (int i = 0; i < 5; ++i) {
char row[6];
cin >> row;
for (int j = 0; j < 5; ++j) {
if (row[j] == '.')
map = map | (1 << (i * 5 + j));
}
}
int result = game(map);
cout << (memo[map] ? "WINNING" : "LOSING") << endl;
}
return 0;
}
반응형
'알고리즘 문제풀이 > 알고리즘 문제해결전략' 카테고리의 다른 글
11.5_알러지가 심한 친구들_ALLERGY (0) | 2023.03.11 |
---|---|
(오답)11.3_게임판 덮기2_BOARDCOVER2 (0) | 2023.03.09 |
9.17_숫자게임_NUMBERGAME (0) | 2023.02.23 |
9.2_여행 짐 싸기_PACKING (0) | 2023.02.22 |
10.4_문자열 합치기_STRJOIN (0) | 2023.02.19 |