이 문제는 정말 고려해야 할게 많게 느껴졌으나 막상 풀고 나서 생각해보면 그리 많지 않았던 것 같다.. 일단 이 코드는 시간이 무척이나 오래 걸리는데 이 역시 처음 코드를 짜기 시작했을 때 구현의 편리성을 위하여 말의 공간관리를 deque을 이용하여 그런 것이므로 속도까지 빠르게 하려면 vector를 사용하자. 그리고 vector사용을 습관화하자..

자세한 코드정보는 주석을 많이 달았으며 언제나 그렇듯 긴 구현 문제를 코딩할 때는 주석과 함수를 쪼개서 만들어두는 것이 실수할 확률을 줄이는 것 같다.

https://github.com/ukjinlee66/BOJ/blob/master/17780.cpp

 

ukjinlee66/BOJ

baekjoon. Contribute to ukjinlee66/BOJ development by creating an account on GitHub.

github.com

https://www.acmicpc.net/problem/17780

 

17780번: 새로운 게임

재현이는 주변을 살펴보던 중 체스판과 말을 이용해서 새로운 게임을 만들기로 했다. 새로운 게임은 크기가 N×N인 체스판에서 진행되고, 사용하는 말의 개수는 K개이다. 말은 원판모양이고, 하나의 말 위에 다른 말을 올릴 수 있다. 체스판의 각 칸은 흰색, 빨간색, 파란색 중 하나로 색칠되어있다. 게임은 체스판 위에 말 K개를 놓고 시작한다. 말은 1번부터 K번까지 번호가 매겨져 있고, 이동 방향도 미리 정해져 있다. 이동 방향은 위, 아래, 왼쪽, 오른쪽

www.acmicpc.net

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
161
162
163
164
#include<iostream>
#include<vector>
#include<deque>
#include<algorithm>
using namespace std;
int n, k;
int map[13][13];
bool level[11];//말이 바닥인지 올라타있는지.
deque<int> M[13][13];//2차원 공간관리.
pair<intint> dir[4= { {0,1},{0,-1},{-1,0},{1,0} }; //-> <- ^ v
vector<pair<intpair<intint>>> hor;//말의 좌표와 방향관리.
void checksize()
{
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
            cout << M[i][j].size() << " ";
        cout << "\n";
    }
}
bool checkturn()
{
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            if (M[i][j].size() >= 4//사이즈가4이상인 말이존재할경우.
            {
                return true;
            }
    return false;
}
void moving(int idx)//말의번호.
{
    if (!level[idx]) return//올라타있는놈일경우 skip.
    int curx = hor[idx].first; //x좌표
    int cury = hor[idx].second.first; // y좌표
    int mo = hor[idx].second.second; //방향
    int nx = curx + dir[mo].first;//이동하려는 x좌표
    int ny = cury + dir[mo].second;//이동하려는 y좌표
    int w = map[nx][ny];
    if (w == 2 || (nx < 0 || ny < 0 || nx >= n || ny >= n))//파랑 일경우 반대바꿔서이동.
    {
        //방향전환.
        if (mo == 0) hor[idx].second.second = 1;
        else if (mo == 1) hor[idx].second.second = 0;
        else if (mo == 2) hor[idx].second.second = 3;
        else hor[idx].second.second = 2;
        mo = hor[idx].second.second; //바뀐방향 업데이트.
        nx = curx + dir[mo].first;
        ny = cury + dir[mo].second;//새로운이동.
        if ((nx < 0 || ny < 0 || nx >= n || ny >= n) || map[nx][ny] == 2)//파랑이거나 범위를넘어간경우.
            return;//방향을바꿧으니 그대로종료.
        else //파랑이거나 범위밖이아니므로 이동.
            moving(idx);
    }
    else if (w == 1)//빨강 덱을뒤집는다.
    {
        //말의좌표와공간을 이동시킨후 공간을 뒤집는다.
        if (M[nx][ny].size() >= 1//빨간공간의 말이 이미 존재할경우.
        {
            while (!M[curx][cury].empty()) //빼면서 현재말의방향으로 전부이동시킨다. 현재칸의뒤에서빼서 뒤로집어넣음.
            {
                int val = M[curx][cury].back(); //말의 idx
                M[curx][cury].pop_back();
                M[nx][ny].push_back(val);
                if (M[nx][ny].size() >= 4)
                    return;
                hor[val].first = nx;
                hor[val].second.first = ny; //말의좌표를바꾸어준다.
                level[val] = false;
            }
        }
        else //없을경우.
        {
            while (!M[curx][cury].empty()) //빼면서 현재말의방향으로 전부이동시킨다. //밑에서빼서 아래로집어넣음.
            {
                int val = M[curx][cury].front();
                M[curx][cury].pop_front();
                M[nx][ny].push_front(val);
                if (M[nx][ny].size() >= 4)
                    return;
                hor[val].first = nx;
                hor[val].second.first = ny; //말의좌표를바꾸어준다. 그 후 꼭대기있던놈만 바닥으로간다.
                level[val] = false;
            }
            level[M[nx][ny].front()] = true;
        }
    }
    else//하양
    {
        if (M[nx][ny].size() >= 1)//말이 이미 존재할경우.
        {
            while (!M[curx][cury].empty())//현재있던칸을 전부비움
            {
                int val = M[curx][cury].front();//말의 번호.
                M[nx][ny].push_back(val);//새로운칸에 말을 쌓아올림.
                if (M[nx][ny].size() >= 4)
                    return;
                M[curx][cury].pop_front();
 
                //말의 좌표변경 방향은 그대로둔다.
                hor[val].first = nx;
                hor[val].second.first = ny;
                level[val] = false;//전부올라탈예정.
            }
        }
        else //말이존재하지않을경우그대로이동. level 변화는없다.
        {
            while (!M[curx][cury].empty())
            {
                int val = M[curx][cury].front();//말의 번호.
                M[nx][ny].push_back(M[curx][cury].front());
                if (M[nx][ny].size() >= 4)
                    return;
                M[curx][cury].pop_front();
 
                //말의 좌표변경 방향은 그대로둔다.
                hor[val].first = nx;
                hor[val].second.first = ny;
            }
        }
    }
    return;
}
int main()
{
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    cin >> n >> k;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            cin >> map[i][j];
    //이동방향 -> <- ^ v 1 2 3 4
    //체스판 0흰 1빨 2파
    for (int i = 0; i < k; i++//체스를 받음.
    {
        int row, column, move;
        cin >> row >> column >> move;
        move--;
        row--;
        column--;
        hor.push_back({ row,{column,move} }); //말의 좌표와 방향을저장.
        M[row][column].push_back(i); //체스판의 공간에 할당.(i번)
        //같은칸에 말이두개이상 입력으로주어지지않는다.
        level[i] = true//초기 모든말은 맨아래 바닥칸에 존재한다.
    }
    int turn = 1;
    while (true)
    {
        if (turn >= 1000) {
            turn = -1;
            break;
        }
        for (int i = 0; i < k; i++) {//말을돌아보며 턴을시작.
            moving(i);
            if (checkturn()) //만약 높이가4이상인말이있을경우 끝냄.
                break;
        }
        /*checksize();*/
        if (checkturn()) //만약 높이가4이상인말이있을경우 끝냄.
            break;
        turn++;//아닐경우 턴을증가.
    }
    cout << turn;
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none;color:white">cs

'Problem Solving > 삼성 역량테스트' 카테고리의 다른 글

BOJ-14500 테트로미노  (0) 2019.11.07
BOJ-17837 새로운 게임2  (0) 2019.11.06
BOJ-12100 2048(Easy)  (0) 2019.11.06
BOJ-17144 미세먼지 안녕  (0) 2019.11.06
BOJ-17779 게리맨더링 2  (0) 2019.11.05

+ Recent posts