[cp-tricki] How to come up with a comparator?

Revision en3, by miaowtin, 2023-07-13 16:56:54

This is a cp-tricki article, inspired by the dead project tricki. The idea of the project is to publish short blogs elaborating on ideas that are too small or simple for a comprehensive tutorial, but still useful for many people.

We do not claim any authorship of these tricks, taking our primary purpose to popularise them, so we hope that somebody will find these ideas fruitful.


Acknowledgements.

We start from a simple trick, which was exposed by Sergei Kopeliovich at Winter Programming School in Kharkiv in 2013.

Short description.

If it seems that a problem can be solved by an algorithm of the form: "arrange the objects in a suitable way and then work greedily", there is a general strategy to devise a comparator for this sort.

Prerequisites.

No specific knowledge is required, though familiarity with greedy algorithms would be useful.

General description

The auxiliary problem: find an order that optimises a construction (that is the essential part of the considered problem) if it is known that such an order exists.

We first consider a simplified problem, when only two objects exist, say $$$A$$$ and $$$B$$$. Then our comparator should determine which order is better: $$$AB$$$ or $$$BA$$$. To do so, we can normally introduce a penalty (or a cost) function $$$f(A,B)$$$ denoting the amount of penalty (or cost) we have if one takes object $$$A$$$ first and object $$$B$$$ second. Then our comparator chooses that order in which the penalty is minimal (or cost is maximal). If this comparator (relation) $$$A\prec B$$$ (which is $$$A\prec B \iff penalty(A,B)<penalty(B,A)$$$ or $$$cost(A,B)>cost(B,A)$$$) is transitive (i.e. if $$$A\prec B$$$ and $$$B\prec C$$$ then $$$A\prec C$$$) then after sorting all the objects with respect to it we shall obtain the optimal order.

The main problem: find a maximal-size subset that optimises a construction. (The difference from idea 1 is that we are not forced to take all elements.)

To do so, we use the comparator from the auxiliary problem, and take objects greedily one by one. At each step, we make a choice:

  1. Put this object into the answer set,

  2. Replace an instance in the answer set with this object.

More generally one can write here a knapsack-like dp (if we have a subset we know the order by the auxiliary problem).

Example 1.

Given $$$n$$$ boxes, each of which has its weight $$$m_i$$$ and the weight it can carry on the top $$$a_i$$$, determine the size of the largest tower one can build.

Explanations

Example 2 (this CSES problem).

Given $$$n$$$ people and their programmer skill ($$$skill_1$$$) and artistic skill ($$$skill_2$$$). We need to take exactly $$$a$$$ programmers and $$$b$$$ artists. Maximise total skill.

Explanations

Online Judges

  1. https://www.eolymp.com/en/problems/4701 (problem from Example 1, only Russian statement available)
  2. https://www.eolymp.com/en/problems/9640
  3. https://www.eolymp.com/en/problems/1591
  4. https://www.eolymp.com/en/problems/2219
  5. https://www.eolymp.com/en/problems/4699 (only Russian statement available)
  6. https://codeforces.com/gym/104397/problem/A
Tags cp-tricki, tricks, sorting, greedy

History

 
 
 
 
Revisions
 
 
  Rev. Lang. By When Δ Comment
en3 English miaowtin 2023-07-13 16:56:54 46 Tiny change: 'ilable) \n' -> 'ilable) \n6. https://codeforces.com/gym/104397/problem/A'
en2 English miaowtin 2023-07-11 01:55:37 25 Tiny change: 'alty(B,A)$) is' -> 'alty(B,A)$ or $cost(A,B)>cost(B,A)$) is'
en1 English miaowtin 2023-07-11 01:36:50 5923 Initial revision (published)