Notice
Recent Posts
Recent Comments
Link
«   2026/06   »
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
Archives
Today
Total
관리 메뉴

dh-winternagi 님의 블로그

(14908) 구두 수선공 본문

백준 (C++)/Solve

(14908) 구두 수선공

dh-winternagi 2026. 4. 23. 16:19

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

단계별로 풀어보기

42단계(그리디 알고리즘 2) 5번째

 

 

 

ATM에서 간단하게 설명했던 Exchange argument 기법을 더 적극적으로 사용하는 문제.

어떤 두 사람 i, j에 대해 x초에 i→j 순서로 일을 했을 때와 j→i 순서로 일을 했을 때 보상금은 아래와 같다.

1) i→j일 때 i에게 주는 보상금은 x*Si, j에게 주는 보상금은 (x+Ti)*Sj

2) j→i일 때 j에게 주는 보상금은 x*Sj, i에게 주는 보상금은 (x+Tj)*Si

같은 값은 비교 의미가 없으니 빼고 다른 값만 비교하면 첫 번째의 보상금은 Ti*Sj, 두 번째의 보상금은 Tj*Si이다.

Ti+Tj=Tj+Ti이므로 두 사람 순서가 바뀌어도 앞뒤 사람들의 보상금에는 영향이 없다.

따라서 이 값이 작은 순서대로 정렬을 하면 된다.

 

사실 이 정렬 순서는 시간 대비 보상금(Ti/Si)을 기준으로 정렬한 것과 같은데, 실수 자료형을 피하고 (이 문제는 아니지만) Si가 0인 경우를 대비해 교차 곱셈 형태로 정렬한 것이다. 이렇게 두 요소가 섞여 있어도 정렬의 수학적 규칙인 추이성과 비대칭성만 만족한다면 상관이 없다.

 

 

 

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() 
{
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  cout.tie(NULL);
  
  int n;
  
  cin >> n;
  
  vector<pair<int,pair<int,int>>> v(n);
  
  for(int i=0;i<n;i++){
    cin >> v[i].second.first >> v[i].second.second;
    v[i].first= i+1;
  }
  
  sort(v.begin(), v.end(), [](auto A, auto B){
    int Ares= A.second.first*B.second.second;
    int Bres= B.second.first*A.second.second;
    
    if(Ares!=Bres)  return Ares<Bres;
    return A.first<B.first;
  });
  
  for(auto elem:v)  cout << elem.first << " ";
  
  return 0;
}

'백준 (C++) > Solve' 카테고리의 다른 글

(12776) Swap Space  (0) 2026.04.23
(16496) 큰 수 만들기  (0) 2026.04.23
(14464) 소가 길을 건너간 이유 4  (0) 2026.04.23
(28340) K-ary Huffman Encoding  (0) 2026.04.23
(10775) 공항  (0) 2026.04.23