[ 백준 / 1202 ] 보석 도둑 (C++)

2025. 1. 4. 17:51·PS/백준

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

 

난이도 : 골드 2 
알고리즘 유형 : 그리디, 우선순위 큐
풀이 시간 : 1시간 25분 

문제 풀이 

각 보석은 무게 $M_i$와 가격 $V_i$를 가지고 있고, 상근이는 무게가 $C_i$인 가방을 K개 가지고 있고, 이 가방에는 한 개의 보석만 담을 수 있다. 상덕이가 훔칠 수 있는 보석의 최대 가격을 구해보자.

 

문제의 조건을 확인해보면 보석의 총 개수와 가방의 개수가 $1 ≤ N, K ≤ 300000$ 이고, 보석의 정보는 $1 ≤ M_i, V_i ≤ 1000000$이다. 

 

먼저 베낭 문제처럼 각 보석의 개수와 가방의 총 개수에 대한 완전 탐색을 진행하게 되면 $300000 * 300000$으로 무조건 시간초과가 난다. 따라서, 우리는 그리디 알고리즘을 사용해서 최적의 경우에 대해 판단해야한다.

또한, 만약 보석이 총 $300000$ 개가 있고, 각 보석의 가치가 모두 $1000000$이라면, 이는 int형의 범위를 충분히 넘어가게 된다. 따라서, int 형 대신 long long int 형을 사용하여 문제를 풀어나가야 한다.

 

문제를 풀이하는 데 핵심은 정렬과 우선순위 큐 이다.우리는 그리디하게 문제를 해결해야 하기 때문에, 먼저 보석의 크기가 큰 순서대로 순회를 하며 크기가 큰 가방 순서대로 담을 것이다. 여기서 조건문을 사용한다면, (조건 1)사용할 수 있는 가방이 있고, 보석의 무게가 가방의 제한 무게보다 낮거나 같은 경우에 가방에 보석을 담을 것이다.

 

만약, (조건 1)을 만족하지 않는다면,우선순위 큐를 사용할 것이다. 

우선순위 큐에는 <보석의 값이 낮은 순, 값이 같을 경우, 가방의 무게가 낮은 순> 으로 우선순위를 정해서 담을 것이다. 이후 (조건 1)을 만족하지 않는 경우, 우선순위큐의 top과 현재 보석을 비교할 것이다.

 

만약 보석의 값이 우선순위 큐의 가격보다 크고, 가방에 넣을 수 있다면 현재 우선순위 큐의 맨 앞 값을 빼주고, 새로운 보석값을 더해준다. 여기서 가방의 사이즈는 무게가 큰 순으로 설정하였기 때문에 신경쓰지 않아도 된다.

 

이렇게 그리디 알고리즘 로직을 작성한다면, 시간복잡도 $O(n)$ 내에 문제를 해결할 수 있다.

 

코드

/*
각 보석은 무게 m과 가격 v를 갖고 있다.
상근이는 가방을 k개 갖고있다.
각 가방에 담을 수 있는 최대 무게는 c이다.
가방에는 최대 한 개의 보석만 넣을 수 있다.
훔칠 수 있는 보석의 최대 가격은 ?

풀이 : 
2중 for문을 돌아야 하기 때문에 시간초과 -> 냅색 불가능
그렇다면 ,, n개 줄 안에 무조건 끝내야한다.

heapq로 가방을 관리하자 ?
heapq로는 무조건 가방을 넣을 수 있도록 해야하기 때문에, 들어갈 자리가 있는지 확인하기

*/

#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
#define INIT cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
#define lli long long int

using namespace std;

lli n, k;
lli c;

bool cmp(pair<lli, lli> a, pair<lli, lli> b) {
	if (a.first == b.first)
		return a.second < b.second;
	return a.first < b.first;
}

struct cmp2 {
	bool operator()(pair<lli, lli> a, pair<lli, lli> b) {
		if (a.second == b.second)
			return a.first < b.first;
		return a.second > b.second;
	}
};


int main() {
	INIT;
	cin >> n >> k;
	vector<pair<lli, lli>> jewelry(n);
	vector<lli> bagpack(k);
	for (int i = 0; i < n; i++)
		cin >> jewelry[i].first >> jewelry[i].second;
	for (int i = 0; i < k; i++)
		cin >> bagpack[i];
	priority_queue<pair<lli, lli>, vector<pair<lli, lli>>, cmp2> pq;

	sort(bagpack.begin(), bagpack.end());
	sort(jewelry.begin(), jewelry.end(), cmp);

	lli ans = 0;
	// 일단 다 넣고 시작하기
	// 만약 넣을 자리 없다면, (보석의 값이 낮은 순, 값이 같을 경우, 가방의 무게가 낮은 순)으로 정렬해서 채워넣기
	for (int i = n - 1; i > -1; i--) {
		if (!bagpack.empty() && bagpack.back() >= jewelry[i].first) {
			ans += jewelry[i].second;
			pq.push({ bagpack.back(), jewelry[i].second });
			bagpack.pop_back();
		}
		// 다 차 있는 경우, pq에서 찾아내기
		else {
			if (!pq.empty() && pq.top().first > jewelry[i].first) {
				if (pq.top().second < jewelry[i].second) {
					int bag = pq.top().first;
					ans += jewelry[i].second - pq.top().second;
					pq.pop();
					pq.push({ bag, jewelry[i].second });
				}
			}
		}
	}

	cout << ans << '\n';

	return 0;
}

배운 점 

본 문제에서 변수의 타입을 신경쓰지 않아 문제를 푸는 데 매우 긴 시간이 걸렸다. C++의 경우, 변수의 범위를 항상 신경쓰고 & 주소공간을 한 번 더 확인하며 문제를 풀어나가야겠다.

728x90
반응형

'PS > 백준' 카테고리의 다른 글

[ 백준 / 1806 ] 부분합 (C++)  (0) 2025.01.06
[ 백준 / 6087 ] 레이저 통신 (C++)  (0) 2025.01.05
[ 백준 / 16197 ] 두 동전 (C++)  (1) 2024.12.30
[ 백준 / 1781 ] 컵라면 (C++)  (0) 2024.12.27
[ 백준 / 16472 ] 고냥이 (Python)  (0) 2024.12.07
'PS/백준' 카테고리의 다른 글
  • [ 백준 / 1806 ] 부분합 (C++)
  • [ 백준 / 6087 ] 레이저 통신 (C++)
  • [ 백준 / 16197 ] 두 동전 (C++)
  • [ 백준 / 1781 ] 컵라면 (C++)
realhackylife
realhackylife
김밥나라의 단무지가 되고싶
  • realhackylife
    realhackyworld !
    realhackylife
  • 전체
    오늘
    어제
  • 글쓰기 관리
  • 개인 블로그

    • Github
    • 분류 전체보기 (76)
      • PS (64)
        • 백준 (35)
        • 프로그래머스 (23)
        • SWEA (4)
        • CodeTree (2)
      • Embedded SW (5)
        • STM32 (5)
      • CS (1)
        • 운영체제 (1)
      • Programming (3)
        • C & C++ (1)
        • Python (0)
        • AUTOSAR (2)
      • 일상 (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 공지사항

  • 인기 글

  • 태그

    티스토리챌린지
    완전탐색
    구현
    투포인터
    알고리즘
    백준
    항해99
    stm32cube
    BFS
    오블완
    이분탐색
    stm32f103rb
    DP
    그래프탐색
    프로그래머스
    Python
    PS
    그리디
    C++
    dfs
  • 최근 댓글

  • hELLO· Designed By정상우.v4.10.0
realhackylife
[ 백준 / 1202 ] 보석 도둑 (C++)
상단으로

티스토리툴바