[BOJ] 전깃줄

Date:

[BOJ] 전깃줄

Problem URL : 전깃줄

[1] 동적 프로그래밍을 이용한 풀이

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

int n;
vector<pair<int, int>> pole;
// dp[i]는 수열의 i번째 원소를 마지막으로 하는 부분수열중 최장 길이
int dp[100]; 


int main()
{   
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    cin >> n;
    int a, b;
    for (int i = 0; i < n; i++)
    {
        cin >> a >> b;
        pole.push_back({ a,b });
    }
    sort(pole.begin(), pole.end());

    dp[0] = 1;
    for (int i = 1; i < n; i++)
    {
        dp[i] = 1;
        for (int j = 0; j < i; j++)
        {
            if (pole[i].second > pole[j].second && dp[i] < dp[j] + 1)
            {
                dp[i] = dp[j] + 1;
            }
        }
    }

    int lis = 1;
    for (int i = 1; i < n; i++)
    {
        if (lis < dp[i]) {
            lis = dp[i];
        }
    }

    cout << n - lis << '\n';
}

[2] lower bound를 이용한 풀이

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

int n;
vector<pair<int, int>> pole;
// cache[n] = 최장증가수열의 (n+1)번째 항
vector<int> cache;

int main()
{
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    cin >> n;
    int a, b;
    for (int i = 0; i < n; i++)
    {
        cin >> a >> b;
        pole.push_back({ a,b });
    }
    sort(pole.begin(), pole.end());
    for (int i = 0; i < n; i++){
        int value = pole[i].second;
        if (cache.empty() || cache.back() < value) {
            cache.push_back(value);
        }else {
            int idx = lower_bound(cache.begin(), cache.end(), value) - cache.begin();
            cache[idx] = value;
        }
    }

    cout << n - cache.size() << '\n';
}

[3] segmentTree를 이용한 풀이

#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
#include<cstring>
#define p pair<int,int>

using namespace std;
const int MAX = 1 << 9;

int segtree[2 * MAX];

void update(int x, int num) {
	segtree[x] = num;
	while (x / 2 > 0) {
		x /= 2;
		segtree[x] = max(segtree[2 * x], segtree[2 * x + 1]);
	}
}
int query(int position, int idx = 1, int s = 1, int e = MAX) {
	if (s > position) return 0;
	if (e <= position) return segtree[idx];

	int mid = (s + e) / 2;
	return max(query(position, 2 * idx, s, mid), query(position, 2 * idx + 1, mid + 1, e));
}

int main() {
	ios_base::sync_with_stdio(false); cout.tie(NULL); cin.tie(NULL);
	memset(segtree, 0, sizeof(segtree));
	int n;
	cin >> n;
	
	priority_queue<p, vector<p>, greater<p>> pq;
	for (int i = 0; i < n; ++i) {
		int position;
		int value;
		cin >> position >> value;
		pq.push({ value, position });
	}
	int ans = 0;
	while (!pq.empty()) {
		int value = pq.top().first;
		int position = pq.top().second;
		pq.pop();
		int t = query(position);
		ans = max(ans, t + 1);
		update(MAX + position, t + 1);
	}
	cout << n - ans << '\n';
		
	return 0;
}

Comments

LIS(Longest Increasing Subsequence) 최장 증가 부분 수열 문제이다. [3] seg[x] : x위치의 수열 값을 끝으로 하는 증가 수열의 최대 길이
이 블로그 를 참조하였다

댓글