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

 

17135번: 캐슬 디펜스

첫째 줄에 격자판 행의 수 N, 열의 수 M, 궁수의 공격 거리 제한 D가 주어진다. 둘째 줄부터 N개의 줄에는 격자판의 상태가 주어진다. 0은 빈 칸, 1은 적이 있는 칸이다.

www.acmicpc.net

<풀이>

1. 격자판을 입력받는다.

2. 궁수 3명을 배치해서, 죽일 수 있는 적의 최대 수를 출력한다.

 

<해법>

1. 알고리즘 선택하기

=> 궁수 3명을 배치할 수 있는 모든 경우를 해보아야 합니다. 따라서, 저는 브루트포스를 선택해서 궁수를 모든 경우에 배치해보았습니다.

 

2. 시뮬레이션 구현하기

=> 궁수 3명을 배치한 이후에는 시뮬레이션을 진행해야합니다. 시뮬레이션의 핵심은 문제의 조건에 맞게 정확하게 구현하는 것입니다. 구현방법은 아래의 코드를 참조해주세요.

 

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
#include <iostream>
#include <string.h>
#include <algorithm>
#include <vector>
 
using namespace std;
 
struct pos {
    int x, y;
};
 
struct enemy {
    pos p;
    int dist;
};
 
int N, M, D;
int map[15][15];
int map_copy[15][15];
int archer[3];
int answer;
 
bool cmp(enemy e1, enemy e2) {
    if (e1.dist == e2.dist) {
        if (e1.p.y == e2.p.y) return e1.p.x < e2.p.x;
        return e1.p.y < e2.p.y;
    }
    return e1.dist < e2.dist;
}
 
int getDist(int x1, int y1, int x2, int y2) {
    return abs(x1 - x2) + abs(y1 - y2);
}
 
bool isNoEnemy(int col) {
    for (int i = 0; i < col; i++) {
        for (int j = 0; j < M; j++) {
            if (map_copy[i][j] == 1return false;
        }
    }
    return true;
}
 
void copyMap() {
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            map_copy[i][j] = map[i][j];
        }
    }
}
 
int countDeadEnemy() {
 
    int output = 0;
 
    //1. 시뮬레이션 맵 카피
    copyMap();
    int archerCol = N;
    //2. 시뮬레이션
    while (archerCol >= 1) {
        if (isNoEnemy(archerCol)) break;
        //(1) 모든 궁수마다 죽일 적 선택하기
        vector<pos> kill;
        for (int i = 0; i < 3; i++) {
            vector<enemy> v;
            //적 담기
            for (int j = 0; j < archerCol; j++) {
                for (int k = 0; k < M; k++) {
                    if (map_copy[j][k] == 1) {
                        int dist = getDist(archerCol, archer[i], j, k);
                        if (dist <= D) v.push_back({ {j,k},dist });
                    }
                }
            }
            //정렬
            sort(v.begin(), v.end(), cmp);
            //죽일 적 1명 담기
            if (!v.empty()) kill.push_back(v.front().p);
        }
        //(2) 적 죽이기
        for (auto& k : kill) {
            if (map_copy[k.x][k.y] == 1) {
                map_copy[k.x][k.y] = 0;
                output++;
            }
        }
        //(3) 궁수 라인 올리기
        archerCol--;
    }
 
    return output;
}
 
int selectArcherPos(int idx, int cnt) {
 
    if (cnt == 3return countDeadEnemy();
 
    int ret = 0;
    for (int i = idx; i < M; i++) {
        archer[cnt] = i;
        ret = max(ret, selectArcherPos(i + 1, cnt + 1));
    }
    return ret;
}
 
void solution() {
    answer = selectArcherPos(00);
}
 
int main() {
    //초기화
    N = 0, M = 0, D = 0;
    memset(map, 0sizeof(map));
    memset(map_copy, 0sizeof(map_copy));
    memset(archer, 0sizeof(archer));
    answer = 0;
 
    //입력
    cin >> N >> M >> D;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            cin >> map[i][j];
        }
    }
 
    //해법
    solution();
 
    //출력
    cout << answer << "\n";
 
    //종료
    return 0;
}

 

브루트포스와 시뮬레이션에 대해 알아볼 수 있는 문제였습니다.

+ Recent posts