Algorithm, Data structure/Solved Algorithmic Problem

BAEKJOON 1006 - 습격자 초라기

JaykayChoi 2016. 7. 21. 23:30

문제: https://www.acmicpc.net/problem/1006


처음에는 brute force 로 풀어봤으나 최대 N 의 값이 10000 이기 때문에 시간이 초과됩니다. 

따라서 memoization 방법을 사용해야 되는데 그러기 위해서는 1번부터 N - 1 까지 순차적으로 우측 방향으로만 진행하며 경우의 수를 찾아야 됩니다. 

이때 문제는 1번과 N + 1번에서 왼쪽으로 진행되는 방향은 고려되지 않는다는 점이 문제입니다. 해당 부분에 대해 한참 고민을 하다 사이트의 질문 검색을 통해 하드 코딩을 하는 방법으로 조언을 얻어 해결 했습니다.



my solving

c++

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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
#include <fstream>
#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <cstring>
using namespace std;
 
int numArea, numTroopsPerUnit;
int enemies[10001][2];
int cache[10001][2];
 
 
#pragma region brute force / It used more than the allotted runtime
vector<int> enemies_ForBruteForce;
 
//direction: 1 left, 2 right, 3 opposite side
int getImmediateArea(int curPos, int direction)
{
    switch (direction)
    {
    case 1:
        if (curPos == 0)
            return numArea - 1;
        else if (curPos == numArea)
            return numArea * - 1;
        else
            return curPos - 1;
    case 2:
        if (curPos == numArea - 1)
            return 0;
        else if (curPos == numArea * - 1)
            return numArea;
        else
            return curPos + 1;
    case 3:
        if (curPos < numArea)
            return curPos + numArea;
        else
            return curPos - numArea;
    default:
        break;
    }
    return -1;
}
 
int bruteForce(set<int>& put)
{
    if (put.size() == numArea * 2)
        return 0;
 
    int ret = 0;
    for (int i = 0; i < numArea * 2; i++)
    {
        set<int>::iterator it = put.find(i);
        if (it != put.end())
            continue;
 
        for (int direction = 0; direction <= 3; direction++)
        {
            if (direction == 0)
            {
                put.insert(i);
                bruteForce(put);
                put.erase(i);
            }
            else
            {
                int immediateArea = getImmediateArea(i, direction);
                it = put.find(immediateArea);
                if (it != put.end())
                    continue;
 
                if (enemies_ForBruteForce[i] + enemies_ForBruteForce[immediateArea] <= numTroopsPerUnit)
                {
                    put.insert(i);
                    put.insert(immediateArea);
                    int candidate = bruteForce(put) + 1;
                    ret = max(ret, candidate);
                    put.erase(i);
                    put.erase(immediateArea);
                }
            }
        }
    }
    return ret;
}
#pragma endregion
 
 
bool canAttackTwoAreas(int column1, int row1, int column2, int row2)
{
    if (column1 >= numArea || column2 >= numArea)
        return false;
    return enemies[column1][row1] + enemies[column2][row2] <= numTroopsPerUnit;
}
 
int dp(int column, int row)
{
    if (column >= numArea)
        return 0;
 
    int& ret = cache[column][row];
    if (ret != -1)
        return ret;
 
    ret = -1;
 
    if (column == numArea - 1)
    {
        if (row == && canAttackTwoAreas(numArea - 10, numArea - 11))
            return 1;
 
        return 0;
    }
 
    if (row == 0)
    {
        if (canAttackTwoAreas(column, 0, column, 1))
            ret = max(ret, dp(column + 10+ 1);
 
        if (canAttackTwoAreas(column, 0, column + 10))
        {
            if (canAttackTwoAreas(column, 1, column + 11))
                ret = max(ret, dp(column + 20+ 2);
            ret = max(ret, dp(column + 11+ 1);
        }
 
        ret = max(ret, dp(column, 1));
    }
    else
    {
        if (canAttackTwoAreas(column, 1, column + 11))
        {
            if (canAttackTwoAreas(column + 10, column + 20))
                ret = max(ret, dp(column + 21+ 2);
 
            ret = max(ret, dp(column + 20+ 1);
        }
 
        ret = max(ret, dp(column + 10));
    }
 
    return ret;
}
 
 
int main()
{
    int cases;
    cin >> cases;
 
    for (int i = 0; i < cases; i++)
    {
        cin >> numArea >> numTroopsPerUnit;
 
        for (int i = 0; i < 2; i++)
        {
            for (int j = 0; j < numArea; j++)
            {
                int num;
                cin >> num;
                enemies[j][i] = num;
            }
        }
 
        memset(cache, -1sizeof(cache));
 
        int twoAreas = dp(00);
    
        if (numArea > 1)
        {
            int temp[2][2];
 
            for (int i = 0; i < 2; i++)
            {
                temp[0][i] = enemies[numArea - 1][i];
                temp[1][i] = enemies[0][i];
            }
 
            if (canAttackTwoAreas(numArea - 1000&& canAttackTwoAreas(numArea - 1101))
            {
                enemies[numArea - 1][0= numTroopsPerUnit + 1;
                enemies[numArea - 1][1= numTroopsPerUnit + 1;
 
                memset(cache, -1sizeof(cache));
                twoAreas = max(twoAreas, dp(10+ 2);
 
                enemies[numArea - 1][0= temp[0][0];
                enemies[numArea - 1][1= temp[0][1];
            }
 
            if (canAttackTwoAreas(numArea - 1000))
            {
                enemies[numArea - 1][0= numTroopsPerUnit + 1;
 
                memset(cache, -1sizeof(cache));
                twoAreas = max(twoAreas, dp(01+ 1);
 
                enemies[numArea - 1][0= temp[0][0];
            }
 
            if (canAttackTwoAreas(numArea - 1101))
            {
                enemies[numArea - 1][1= numTroopsPerUnit + 1;
                enemies[0][1= numTroopsPerUnit + 1;
 
                memset(cache, -1sizeof(cache));
                twoAreas = max(twoAreas, dp(00+ 1);
            }
        }
        cout << numArea * - twoAreas << endl;
 
    }
 
    return 0;
}
 
cs


'Algorithm, Data structure > Solved Algorithmic Problem' 카테고리의 다른 글

BAEKJOON 1008 - A/B  (0) 2016.07.23
BAEKJOON 1007 - Vector Matching  (0) 2016.07.23
BAEKJOON 1005 - ACM Craft  (0) 2016.07.13
BAEKJOON 1004 - 어린왕자  (0) 2016.07.12
BAEKJOON 1003 - 파보나치 함수  (0) 2016.07.10