예제 입력 1
3
2 2 2
4 4 4
8 8 8
예제 출력 1
16
https://www.acmicpc.net/problem/12100
12100번: 2048 (Easy)
첫째 줄에 보드의 크기 N (1 ≤ N ≤ 20)이 주어진다. 둘째 줄부터 N개의 줄에는 게임판의 초기 상태가 주어진다. 0은 빈 칸을 나타내며, 이외의 값은 모두 블록을 나타낸다. 블록에 쓰여 있는 수는 2보다 크거나 같고, 1024보다 작거나 같은 2의 제곱꼴이다. 블록은 적어도 하나 주어진다.
www.acmicpc.net
- 최대 5회 이므로, 각 이동케이스를 길이가 5인 4진법 수 4개로 변환해 각각의 경우를 모두 수행한다.
- 직접 풀어볼 것.
[ 모범 답안 (출처 : code.plus 알고리즘 중급 강의) ]
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int dx[] = { 0, 0, 1, -1 };
int dy[] = { 1, -1, 0, 0 };
const int LIMIT = 5;
vector<int> gen(int k)
{
vector<int> a(LIMIT);
for (int i = 0; i < LIMIT; i++)
{
a[i] = (k & 3);
k >>= 2;
}
return a;
}
int check(vector<vector<int>>& a, vector<int>& dirs)
{
int n = a.size();
// 합쳐졌는지 여부와 게임판을 함께 저장
vector<vector<pair<int, bool>>> d(n, vector<pair<int, bool>>(n));
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
d[i][j].first = a[i][j];
}
}
// 0 : down, 1 : up, 2 : left, 3 : right
for (int dir : dirs)
{
bool ok = false;
// 합쳐졌는지 여부 초기화
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
d[i][j].second = false;
}
}
while (true) // 더이상 안움직일때까지 한 칸씩 움직인다.
{
ok = false;
if (dir == 0) // 아래 방향, 합쳐질때 아래부터 합쳐지므로 아래부터 Loop
{
for (int i = n - 2; i >= 0; i--)
{
for (int j = 0; j < n; j++)
{
if (d[i][j].first == 0) continue; // 숫자가 없으면 그냥 지나감
if (d[i + 1][j].first == 0) // 이동 방향이 비어있다.
{
d[i + 1][j].first = d[i][j].first;
d[i + 1][j].second = d[i][j].second;
d[i][j].first = 0;
ok = true;
}
else if (d[i + 1][j].first == d[i][j].first) // 같은숫자. 합쳐짐
{
// 합쳐진적 없으면
if (d[i][j].second == false && d[i + 1][j].second == false)
{
d[i + 1][j].first *= 2;
d[i + 1][j].second = true;
d[i][j].first = 0;
ok = true;
}
}
}
}
}
else if (dir == 1) {
for (int i = 1; i < n; i++) {
for (int j = 0; j < n; j++) {
if (d[i][j].first == 0) continue;
if (d[i - 1][j].first == 0) {
d[i - 1][j].first = d[i][j].first;
d[i - 1][j].second = d[i][j].second;
d[i][j].first = 0;
ok = true;
}
else if (d[i - 1][j].first == d[i][j].first) {
if (d[i][j].second == false && d[i - 1][j].second == false) {
d[i - 1][j].first *= 2;
d[i - 1][j].second = true;
d[i][j].first = 0;
ok = true;
}
}
}
}
}
else if (dir == 2) {
for (int j = 1; j < n; j++) {
for (int i = 0; i < n; i++) {
if (d[i][j].first == 0) continue;
if (d[i][j - 1].first == 0) {
d[i][j - 1].first = d[i][j].first;
d[i][j - 1].second = d[i][j].second;
d[i][j].first = 0;
ok = true;
}
else if (d[i][j - 1].first == d[i][j].first) {
if (d[i][j].second == false && d[i][j - 1].second == false) {
d[i][j - 1].first *= 2;
d[i][j - 1].second = true;
d[i][j].first = 0;
ok = true;
}
}
}
}
}
else if (dir == 3)
{
for (int j = n - 2; j >= 0; j--) {
for (int i = 0; i < n; i++) {
if (d[i][j].first == 0) continue;
if (d[i][j + 1].first == 0) {
d[i][j + 1].first = d[i][j].first;
d[i][j + 1].second = d[i][j].second;
d[i][j].first = 0;
ok = true;
}
else if (d[i][j + 1].first == d[i][j].first) {
if (d[i][j].second == false && d[i][j + 1].second == false) {
d[i][j + 1].first *= 2;
d[i][j + 1].second = true;
d[i][j].first = 0;
ok = true;
}
}
}
}
}
if (ok == false) break; // 더이상 이동할 수 없다.
}
}
int ans = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (ans < d[i][j].first) {
ans = d[i][j].first;
}
}
}
return ans;
}
int main(void)
{
int n;
cin >> n;
vector<vector<int>> a(n, vector<int>(n));
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
cin >> a[i][j];
}
}
int ans = 0;
for (int k = 0; k < (1 << (LIMIT * 2)); k++)
{
vector<int> dir = gen(k);
int cur = check(a, dir);
if (ans < cur) ans = cur;
}
cout << ans << '\n';
return 0;
}
'Algorithm > 문제풀이' 카테고리의 다른 글
[BFS] 데스 나이트 (0) | 2019.10.14 |
---|---|
[BFS] 뱀과 사다리 게임 (0) | 2019.10.14 |
★ [Brute Force - 비트마스크] 구슬 탈출 2 (0) | 2019.10.09 |
★ [Brute Force - 비트마스크] 가르침 (0) | 2019.10.09 |
[Brute Force - 비트마스크] 부분수열의 합 (0) | 2019.10.03 |