일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- anomaly detection
- Stack
- 그리디
- DP
- Deeplearning
- classification
- 스택
- 알고리즘
- p-value
- Python
- Game Data Analysis
- Anti Cheat
- Journal Review
- 자료구조
- 구현
- datascience
- AA test
- 통계
- 백준
- 딥러닝
- BFS
- Queue
- c++
- ML
- 중앙갑
- cs231n
- Machine learning
- 7569번
- 큐
- 정렬
- Today
- Total
Software Hyena::
[백준 2238번] - 경매 / C++ (stable_sort) 본문
www.acmicpc.net/problem/2238
2238번: 경매
첫째 줄에 두 정수 U(1≤U≤10,000), N(1≤N≤100,000)이 주어진다. U는 금액의 상한이고, N은 경매에 참여한 회수이다. 다음 N개의 줄에는 사람 이름 S(공백 없는 알파벳 대소문자 10자 이하)와, 그 사람
www.acmicpc.net
문제
경매는 여러 사람이 하나의 물건을 사려고 할 때, 각 사람이 원하는 가격을 제시하면 그 중 가장 높은 가격으로 물건을 팔게 되는 방식이다. 이러한 고전적인 경매 방식은 꽤 널리 쓰이는데, 최근에는 인터넷 쇼핑몰에서 반대의 경매 방식을 택하기도 한다. 즉, 여러 사람이 가격을 제시하면, 그 중 가장 낮은 가격으로 물건을 팔게 되는 방식도 쓰인다.
하지만 이럴 경우, 모든 사람들이 1원에 물건을 사겠다고 하는 사태가 발생할 수 있다. 따라서 같은 가격을 제시한 사람이 둘 이상일 경우에는 무효로 하는 방식이 쓰인다. 하지만 모든 가격을 여러 사람이 제시하는 경우도 있을 수 있기 때문에, 다음과 같은 방식으로 경매 당첨자를 선택하기로 한다.
우선 가장 적은 수의 사람이 제시한 가격을 찾는다. 이러한 경우가 여럿 있다면, 가장 낮은 가격으로 물건을 팔게 된다. 이때, 그 가격을 제시한 사람들 중에서 가장 먼저 제시한 사람이 물건을 살 수 있게 된다.
각각의 사람들이 제시한 가격이 주어졌을 때, 경매에 낙찰(당첨)되는 사람을 구하는 프로그램을 작성하시오.
입력
첫째 줄에 두 정수 U(1≤U≤10,000), N(1≤N≤100,000)이 주어진다. U는 금액의 상한이고, N은 경매에 참여한 회수이다. 다음 N개의 줄에는 사람 이름 S(공백 없는 알파벳 대소문자 10자 이하)와, 그 사람이 제시한 가격 P(1≤P≤U, 정수)이 경매에 참여한(가격을 제시한) 순서대로 주어진다.
출력
첫째 줄에 낙찰된 사람의 이름과 그 가격을 출력한다.
----------------------------------------------------------------------------------------------------
풀이
<C++>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
pair<int,int> arr[100001];
bool Acending(pair<string, int> a, pair<string, int> b) {
return a.second < b.second;
}
bool Acending2(pair<int, int> a, pair<int, int> b) {
if (a.second == b.second) {
return a.first < b.first;
}
return a.second < b.second;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int U;
cin >> U;
int N;
cin >> N;
string name;
int money;
vector<pair<string, int>> v;
for (int i = 0; i < N; ++i) {
cin >> name >> money;
v.push_back({ name, money });
}
stable_sort(v.begin(), v.end(), Acending);
string answerName;
int answerMoney;
bool truelyEnd = false;
for (int i = 0; i < N - 2; ++i) {
if (v[i].second == v[i + 1].second) {
if (i == N - 3) {
if (v[i + 1].second < v[i + 2].second) {
answerName = v[i + 2].first;
answerMoney = v[i + 2].second;
truelyEnd = true;
break;
}
}
else {
continue;
}
}
else if (v[i].second < v[i + 1].second) {
if (i == 0) {
answerName = v[i].first;
answerMoney = v[i].second;
truelyEnd = true;
break;
}
else if (v[i + 2].second > v[i + 1].second) {
answerName = v[i + 1].first;
answerMoney = v[i + 1].second;
truelyEnd = true;
break;
}
else {
continue;
}
}
}
if (truelyEnd) {
cout << answerName << ' ' << answerMoney;
}
else {
for (int i = 0; i < N; ++i) {
arr[v[i].second].first = v[i].second;
arr[v[i].second].second += 1;
}
stable_sort(arr, arr + N, Acending2);
int j;
for (int i = N - 1; i >= 0; --i) {
if (arr[i].first == 0) {
j = i + 1;
break;
}
}
for (int i = 0; i < N; ++i) {
if (arr[j].first == v[i].second) {
cout << v[i].first << ' ' << v[i].second;
break;
}
}
}
return 0;
}
solved.ac 기준으로 실버V 문제인데도 불구하고 조건들이 까다로워서 푸는데 꽤나 고생했다. 천천히 코드를 살펴보도록 하자.
1. U와 N을 입력받는다.
2. pair를 갖는 vector에 이름과 경매가를 넣는다.
3. vector에 대해 stable_sort를 진행한다.
- stable_sort 란 sort는 같은 값을 가지는 값들에 대해 원래 입력받은 순서대로 정렬됨을 보장하지 못한다. 이를 보장해주는 것이 stable_sort라고 생각하면 된다.
4. 경매가들의 비교를 진행한다.
-> 값이 같으면, continue
-> 값이 다르면, 그 다음값과도 비교하여 같으면 continue, 다르면 answer에 입력
-> 예외처리, i == 0 인경우와 i == N-2 인경우는 처음과 끝이므로 다르게 처리해준다.
-> 반복문을 모두 돌기전에 올바르게 답을 입력하고 반복문을 탈출했을때는 truelyEnd 라는 boolean 값에 true를 넣어준다. 그렇지 못한 경우 false 그대로 유지.
5. boolean 이 true인 경우, 그냥 답을 출력한다.
6. boolean 이 false인 경우, 경매가와 중복횟수를 pair로 묶은뒤 이를 모두 arr 배열에 담는다. 그리고 arr에 대한 stable_sort를 진행한다.
7. arr배열을 전역으로 선언했으므로 pair 쌍이 {0, 0}으로 채워져 있다. 따라서 index를 N-1부터 빼가면서 {0,0} 인 index를 찾고, 찾은 경우 index에 1을 더해 최소횟수를 가지는 값을 가지는 index를 찾는다.
8. 마지막 반복문에서 arr배열의 최소횟수를 가지는 가격과 vector를 비교하여 가장 첫번째로 같은 값이 나오면 그 index의 이름과 가격을 출력한다.
----------------------------------------------------------------------------------------------------
푸는데 2시간정도 걸린 문제인데 분명히 간단하게 푸는 방법이 있을 것이라고 생각한다. 코드를 간략화하는 작업을 좀 해보아야겠다. 혹시나 좋은 답안이 있다면 댓글로 알려주시면 감사하겠습니다.
'알고리즘 > 백준' 카테고리의 다른 글
[백준 2246번] - 콘도 선정 / C++ (0) | 2021.02.22 |
---|---|
[백준 1783번] - 병든 나이트 / C++ (0) | 2021.02.22 |
[백준 9084번] - 동전 / C++ (0) | 2021.02.21 |
[백준 15688번] - 수 정렬하기 5 / C++ (sync_with_stdio, cin.tie, cout.tie) (0) | 2021.02.20 |
[백준 11557번] - Yangjojang of The Year / C++ (0) | 2021.02.20 |