BOJ : https://www.acmicpc.net/problem/2568

 

2568번: 전깃줄 - 2

첫째 줄에는 두 전봇대 사이의 전깃줄의 개수가 주어진다. 전깃줄의 개수는 100,000 이하의 자연수이다. 둘째 줄부터 한 줄에 하나씩 전깃줄이 A전봇대와 연결되는 위치의 번호와 B전봇대와 연결되는 위치의 번호가 차례로 주어진다. 위치의 번호는 500,000 이하의 자연수이고, 같은 위치에 두 개 이상의 전깃줄이 연결될 수 없다. 

www.acmicpc.net

문제 해결을 위한 알고리즘 : lis

2007년도 지역본선 중등부3번 문제

 

가장 긴 증가하는 부분수열4 : https://junho0956.tistory.com/9?category=825556 

이 문제에서 언급했듯이 lis 알고리즘의 문제점은 lis 배열의 정확한 값을 찾을 수 없다는 것이다.

그러므로 이 문제를 해결하기 위해서는 lis 알고리즘 뿐만 아니라 정확한 값을 찾아가는 추적 알고리즘이 필요하다.

 

lis 알고리즘을 사용하면 사용한 전깃줄에 대한 정보를 가지게 되므로,

사용하지 않은 전깃줄을 출력하기 위해서 bool의 visit 배열을 사용하였다.

 

방식은 일단 먼저 입력되는 전깃줄은 전부 true를 시킨 후에

lis 추적 알고리즘으로 사용된 전깃줄을 다시 false 시키면

결국 남아있게 되는 visit 배열의 true 값을 가진 인덱스가 사용하지 않은 전깃줄이 되게 된다.

 

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
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
 
vector<pair<intint> > arr;
vector<pair<intint> > v;
bool visit[500001];
int lis[500001];
int n, f, s, cnt, L;
 
int _lower_bound(int start, int endint key) {
    int mid;
    while (start < end) {
        mid = (start + end/ 2;
        if (lis[mid] < key)
            start = mid + 1;
        else
            end = mid;
    }
    return end + 1;
}
 
int main() {
    scanf("%d"&n);
    for (int i = 0; i < n; i++) {
        scanf("%d%d"&f, &s);
        v.push_back(make_pair(f, s));
        visit[f] = true;
    }
    sort(v.begin(), v.end());
 
    lis[0= v[0].second;
    arr.push_back({ 0,v[0].first });
 
    for (int i = 1; i < n; i++) {
        if (lis[L] < v[i].second) {
            lis[++L] = v[i].second;
 
            arr.push_back({ L,v[i].first });
        }
        else {
            int ans = _lower_bound(0, L, v[i].second);
            lis[ans - 1= v[i].second;
 
            arr.push_back({ ans - 1, v[i].first });
            cnt++;
        }
    }
    
    for (int i = arr.size(); i >= 0; i--) {
        if (arr[i - 1].first == L) {
            L--, visit[arr[i - 1].second] = false;
        }
        if (L == -1break;
    }
 
    printf("%d\n", cnt);
    for (int i = 1; i < 500001; i++) {
        if (visit[i] == true)
            printf("%d\n", i), cnt--;
        if (cnt == 0break;
    }
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter

위 소스는 직접 lower_bound를 만들어서 사용한 예제이고 아래는 algorithm 헤더로 함수를 바로 사용해본 소스이다.

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
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
 
vector<pair<intint> > arr;
vector<pair<intint> > v;
bool visit[500001];
vector<int> lis;
int n, f, s, cnt, L;
 
int main() {
    scanf("%d"&n);
    for (int i = 0; i < n; i++) {
        scanf("%d%d"&f, &s);
        v.push_back(make_pair(f, s));
        visit[f] = true;
    }
    sort(v.begin(), v.end());
 
    lis.push_back(v[0].second);
    arr.push_back({ 0,v[0].first});
 
    for (int i = 1; i < n; i++) {
        if (lis[L] < v[i].second) {
            lis.push_back(v[i].second);
 
            arr.push_back({ ++L,v[i].first });
        }
        else {
            vector<int>::iterator ans = lower_bound(lis.begin(), lis.end(), v[i].second);
            int answer = lower_bound(lis.begin(), lis.end(), v[i].second) - lis.begin() + 1;
            *ans = v[i].second;
 
            arr.push_back({ answer - 1, v[i].first });
            cnt++;
        }
    }
    
    for (int i = arr.size(); i >= 0; i--) {
        if (arr[i - 1].first == L) {
            L--, visit[arr[i - 1].second] = false;
        }
        if (L == -1break;
    }
 
    printf("%d\n", cnt);
    for (int i = 1; i < 500001; i++) {
        if (visit[i] == true)
            printf("%d\n", i), cnt--;
        if (cnt == 0break;
    }
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter

algorithm 헤더에 있는 lower_bound 의 사용법

1. iterator 을 사용하는 경우

auto or iterator x = lower_bound(start iterator, end iterator, key);

iterator을 사용하면 주소를 반환하게 된다.

2. index를 사용하는 경우

int val = lower_bound(start iterator, end iterator, key) - start iterator + 1;

이런식으로 사용하면 찾은 값의 인덱스를 return 값으로 반환하게 된다.

 

헤더파일을 사용하니 메모리 사용량이 감소하는 것으로 나타났다.

'algorithm > BOJ' 카테고리의 다른 글

백준 2623번 - 음악프로그램 Junnnho  (0) 2019.05.15
백준 : 1516번 - 게임 개발 Junnnho  (0) 2019.05.14
BOJ 2352번 반도체 설계  (0) 2019.04.08
BOJ 2565번 전깃줄  (0) 2019.04.08
BOJ 14501번 퇴사  (0) 2019.04.07

BOJ : https://www.acmicpc.net/problem/2352

github : https://github.com/junho0956/Algorithm/blob/master/11568/11568/%EC%86%8C%EC%8A%A4.cpp

 

문제 해결을 위한 알고리즘 : lis, dp, greedy

lis 알고리즘을 이용하여 문제를 해결하였고

꼬이지않은 lis 배열 안에 들어간 size 가 최대한 연결할 수 있는 포트가 된다.

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
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
 
typedef vector<int> LIS;
LIS lis;
int main() {
    int n, arr[40001], L;
 
    scanf("%d"&n);
    for (int i = 0; i < n; i++)
        scanf("%d"&arr[i]);
 
    L = 0, lis.push_back(arr[0]);
 
    for (int i = 1; i < n; i++) {
        if (arr[i] > lis[L])
            lis.push_back(arr[i]), L++;
        else {
            vector<int>::iterator ans = lower_bound(lis.begin(), lis.end(), arr[i]);
            *ans = arr[i];
        }
    }
 
    printf("%d", lis.size());
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter

 

복습 20.02.10

'algorithm > BOJ' 카테고리의 다른 글

백준 : 1516번 - 게임 개발 Junnnho  (0) 2019.05.14
2568번 : 전깃줄2 - Junnnho  (0) 2019.04.08
BOJ 2565번 전깃줄  (0) 2019.04.08
BOJ 14501번 퇴사  (0) 2019.04.07
6603번 : 로또 - junnnho  (0) 2019.04.07

BOJ : https://www.acmicpc.net/problem/2565

github : https://github.com/junho0956/Algorithm/blob/master/2565/2565/%EC%86%8C%EC%8A%A4.cpp

 

오름차순 정렬이 되어있어야하고, lis 알고리즘에서 lower_bound의 의미를 알아보자면

ex) 만약 현재 lis의 마지막 second가 5이고 현재 걸려있는 줄의 second가 4이면 꼬여있는 상태가 됨을 의미하고,

     만약 현재 lis의 마지막 second가 5이고 현재 걸려있는 줄의 second가 6이면 꼬이지 않은 상태가 됨을 의미한다.

 

꼬일때 lower_bound -> lis의 길이를 찾는 문제이다

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
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
 
vector<pair<intint> > v;
int lis[501];
int n, f, s, cnt, L;
 
int _lower_bound(int start, int endint key) {
    int mid;
    while (start < end) {
        mid = (start + end/ 2;
        if (lis[mid] < key)
            start = mid + 1;
        else
            end = mid;
    }
    return end + 1;
}
 
int main() {
    scanf("%d"&n);
    for (int i = 0; i < n; i++) {
        scanf("%d%d"&f, &s);
        v.push_back(make_pair(f, s));
    }
    sort(v.begin(), v.end());
    lis[0= v[0].second;
    for (int i = 1; i < n; i++) {
        if (lis[L] < v[i].second) {
            lis[++L] = v[i].second;
        }
        else {
            int ans = _lower_bound(0, L, v[i].second);
            lis[ans - 1= v[i].second;
            cnt++;
        }
    }
    printf("%d", cnt);
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter

 

복습 20.02.10

'algorithm > BOJ' 카테고리의 다른 글

2568번 : 전깃줄2 - Junnnho  (0) 2019.04.08
BOJ 2352번 반도체 설계  (0) 2019.04.08
BOJ 14501번 퇴사  (0) 2019.04.07
6603번 : 로또 - junnnho  (0) 2019.04.07
1182번 : 부분수열의 합 - junnnho  (0) 2019.04.07

BOJ : https://www.acmicpc.net/problem/14501

GitHub : https://github.com/junho0956/Algorithm/blob/master/14501/14501/%EC%86%8C%EC%8A%A4.cpp

 

임의의 오늘(today)부터 일을 시작하여 걸리는 시간(arr[today][0])이 만약 총날짜(N) 보다 같거나 작다면

나는 오늘(today)부터 일해도 되는 것이고, 일이 끝난 today+arr[today][0] 의 날짜부터 일을 재개하면 된다.

결국 첫시작일인 1일부터 N일이 주어지면 1부터 N일까지 할 수 있는 모든 경우를 탐색하여 최대를 찾으면 된다.

 

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
#include <cstdio>
#include <algorithm>
using namespace std;
#pragma warning(disable:4996)
 
int N;
int arr[16][2];
 
int ans(int today) {
    if (today > N) return 0;
 
    int temp = 0;
    if (today + arr[today][0- 1 <= N)
        temp = ans(today + arr[today][0]) + arr[today][1];
 
    temp = max(temp, ans(today + 1));
    return temp;
}
 
int main() {
    scanf("%d"&N);
    for (int i = 1; i <= N; i++) {
        scanf("%d%d"&arr[i][0],&arr[i][1]);
    }
 
    printf("%d", ans(1));
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter

 

복습) 20.02.08

 

'algorithm > BOJ' 카테고리의 다른 글

BOJ 2352번 반도체 설계  (0) 2019.04.08
BOJ 2565번 전깃줄  (0) 2019.04.08
6603번 : 로또 - junnnho  (0) 2019.04.07
1182번 : 부분수열의 합 - junnnho  (0) 2019.04.07
14502번 : 연구소 - Junnnho  (0) 2019.04.07

+ Recent posts