Java - 메모리:115196 KB, 시간: 1716 ms
C++ - 메모리:11696 KB, 시간: 416 ms
자료 구조, 그리디 알고리즘, 우선순위 큐, 정렬
2024년 12월 16일 17:11:06
세계적인 도둑 상덕이는 보석점을 털기로 결심했다.
상덕이가 털 보석점에는 보석이 총 N개 있다. 각 보석은 무게 Mi와 가격 Vi를 가지고 있다. 상덕이는 가방을 K개 가지고 있고, 각 가방에 담을 수 있는 최대 무게는 Ci이다. 가방에는 최대 한 개의 보석만 넣을 수 있다.
상덕이가 훔칠 수 있는 보석의 최대 가격을 구하는 프로그램을 작성하시오.
첫째 줄에 N과 K가 주어진다. (1 ≤ N, K ≤ 300,000)
다음 N개 줄에는 각 보석의 정보 Mi와 Vi가 주어진다. (0 ≤ Mi, Vi ≤ 1,000,000)
다음 K개 줄에는 가방에 담을 수 있는 최대 무게 Ci가 주어진다. (1 ≤ Ci ≤ 100,000,000)
느낀점: 그리디가 무작정 유리한대로 고르기만 하는 쉬운 알고리즘은 아닌 것 같다. 그 유리한 방식을 효과적으로 어떻게 활용할지가 관건이다. 연습이 많이 필요할 것 같다.
설계 시간: 30분고민해보고 1차 실패, 이후에는 참고했다.
💡 설계 아이디어
/**
* Author: yngbao97, Yuk Yejin
* Problem: 보석 도둑_1202
* Date: 2024.12.15
*/
import java.lang.reflect.Array;
import java.util.*;
import java.lang.*;
import java.io.*;
public class Main {
static BufferedReader br;
static BufferedWriter bw;
static StringTokenizer st;
public static void main(String[] args) throws Exception {
br = new BufferedReader(new InputStreamReader(System.in));
bw = new BufferedWriter(new OutputStreamWriter(System.out));
String[] input = br.readLine().split(" ");
int n = Integer.parseInt(input[0]); // 보석의 개수
int k = Integer.parseInt(input[1]); // 가방의 개수
Jewelry[] jewelries = new Jewelry[n];
for (int i = 0; i < n; i++) {
st = new StringTokenizer(br.readLine(), " ");
int weight = Integer.parseInt(st.nextToken());
int value = Integer.parseInt(st.nextToken());
jewelries[i] = new Jewelry(weight, value);
}
int[] bags = new int[k];
for (int i = 0; i < k; i++) {
bags[i] = Integer.parseInt(br.readLine());
}
Arrays.sort(jewelries, (o1, o2) -> {
return o1.weight - o2.weight;
});
Arrays.sort(bags);
PriorityQueue<Jewelry> candidate = new PriorityQueue<>((o1, o2) -> {
return o2.value - o1.value;
});
int jIdx = 0;
long answer = 0L;
for (int w : bags) {
while (jIdx < n && jewelries[jIdx].weight <= w) candidate.add(jewelries[jIdx++]);
if (candidate.isEmpty()) continue;
int value = candidate.poll().value;
answer += value;
}
bw.write(String.valueOf(answer));
bw.flush();
bw.close();
br.close();
}
}
class Jewelry {
int weight;
int value;
Jewelry (int weight, int value) {
this.weight = weight;
this.value = value;
}
}
/**
* Author: yngbao97, Yuk Yejin
* Problem: 보석 도둑_1202
* Date: 2024.12.16
*/
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
class Jewelry {
public:
int weight;
int value;
Jewelry() : weight(0), value(0) {}
Jewelry(int w, int v) : weight(w), value(v) {}
};
struct CompareWeight {
bool operator() (const Jewelry& j1, const Jewelry& j2) {
return j1.weight < j2.weight;
}
};
struct CompareValue {
bool operator() (const Jewelry& j1, const Jewelry& j2) {
return j1.value < j2.value;
}
};
int main() {
int n, k;
cin >> n >> k;
vector<Jewelry> jewelries(n);
for (int i = 0; i < n; i++) {
cin >> jewelries[i].weight >> jewelries[i].value;
}
vector<int> bags(k);
for (int i = 0; i < k; i++) {
cin >> bags[i];
}
sort(jewelries.begin(), jewelries.end(), CompareWeight());
sort(bags.begin(), bags.end());
priority_queue<Jewelry, vector<Jewelry>, CompareValue> candidate;
int idx = 0;
long answer = 0;
for (int b : bags) {
while (idx < n && b >= jewelries[idx].weight) candidate.push(jewelries[idx++]);
if (candidate.empty()) continue;
answer += candidate.top().value;
candidate.pop();
}
cout << answer << endl;
}
true를 반환하면 순서를 유지한다. 따라서 j1.weight < j2.weight 가 true를 반환하면 더 작은 요소가 앞에 위치한다.true를 반환하면 두 요소의 순서를 바꾼다. 따라서 j1.value < j2.value 가 true를 반환하면 더 큰 요소가 앞에 위치한다.즉,
std::sort는 비교 함수에서 "왼쪽 값이 오른쪽 값보다 작다"라고 판단(true)하면 그대로. 따라서 오름차순
std::priority_queue는 비교 함수에서 "왼쪽 값이 오른쪽 값보다 작다"라고 판단(true)하면 두 값의 우선순위를 바꿈. 따라서 내림차순