문제링크
1449번: 수리공 항승
첫째 줄에 물이 새는 곳의 개수 N과 테이프의 길이 L이 주어진다. 둘째 줄에는 물이 새는 곳의 위치가 주어진다. N과 L은 1,000보다 작거나 같은 자연수이고, 물이 새는 곳의 위치는 1,000보다 작거나
www.acmicpc.net
문제
항승이는 품질이 심각하게 나쁜 수도 파이프 회사의 수리공이다. 항승이는 세준 지하철 공사에서 물이 샌다는 소식을 듣고 수리를 하러 갔다.
파이프에서 물이 새는 곳은 신기하게도 가장 왼쪽에서 정수만큼 떨어진 거리만 물이 샌다.
항승이는 길이가 L인 테이프를 무한개 가지고 있다.
항승이는 테이프를 이용해서 물을 막으려고 한다. 항승이는 항상 물을 막을 때, 적어도 그 위치의 좌우 0.5만큼 간격을 줘야 물이 다시는 안 샌다고 생각한다.
물이 새는 곳의 위치와, 항승이가 가지고 있는 테이프의 길이 L이 주어졌을 때, 항승이가 필요한 테이프의 최소 개수를 구하는 프로그램을 작성하시오. 테이프를 자를 수 없고, 테이프를 겹쳐서 붙이는 것도 가능하다.
입력
첫째 줄에 물이 새는 곳의 개수 N과 테이프의 길이 L이 주어진다. 둘째 줄에는 물이 새는 곳의 위치가 주어진다. N과 L은 1,000보다 작거나 같은 자연수이고, 물이 새는 곳의 위치는 1,000보다 작거나 같은 자연수이다.
출력
첫째 줄에 항승이가 필요한 테이프의 개수를 출력한다.
풀이
그리디 알고리즘을 사용하여 앞에서부터 차례대로 테이프를 붙여가며 구멍을 막아주면 된다.
배열을 이용하여 뚫린 부분을 체크해주고 배열의 index는 0부터 뚫린곳 까지의 거리라고 생각하자.
뚫린 부분의 위치에서 0.5를 빼주고 테이프의 길이만큼 더해주면 해당 위치보다 가까운 곳의 뚫린 곳은 모두 막힌다. 따라서 테이프 하나로 막을 수 있는 구멍을 모두 막아주고 마지막 위치부터 다시 뚫린 곳을 찾아 이전에 했던 행동을 모든 구멍이 막힐 때까지 반복적으로 진행하면 된다.
코드
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
|
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int N, L, cnt;
// 1이면 뚫린 곳
bool Line[1001];
bool checkLine() {
for (int i = 0; i < 1001; i++) {
if (Line[i] == true)
return false;
}
return true;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> N >> L;
vector<int> v(N);
// 물이 새는 곳 입력
for (int i = 0; i < N; i++) {
cin >> v[i];
Line[v[i]] = true;
}
// 현재 위치
double cur = v[0] - 0.5 + L;
cnt++;
while (!checkLine()) {
// 테이프 하나로 막을 수 있는 곳 막고
for (int i = 0; i < cur; i++) {
if (Line[i] == true) {
Line[i] = false;
}
}
// 막지 못한 곳 찾으면 위에 반복
for (int i = cur + 1; i < 1001; i++) {
if (Line[i] == true) {
Line[i] = false;
cur = i - 0.5 + L;
cnt++;
break;
}
}
}
cout << cnt;
}
|
cs |
메모
[C++] 백준 1471번:국회의원 선거 (그리디 알고리즘)
문제링크 1417번: 국회의원 선거 첫째 줄에 후보의 수 N이 주어진다. 둘째 줄부터 차례대로 기호 1번을 찍으려고 하는 사람의 수, 기호 2번을 찍으려고 하는 수, 이렇게 총 N개의 줄에 걸쳐 입력이
krrong.tistory.com