Problem A: Bus to Pénjamo
The key to maximizing happiness is to seat family members together as much as possible. If two members of the same family sit in the same row, both will be happy, and we only use two seats. However, if they are seated separately, only one person is happy, but two seats are still used. Therefore, we prioritize seating family pairs together first.
Once all possible pairs are seated, there may still be some family members left to seat. If a family has an odd number of members, one person will be left without a pair. Ideally, we want to seat this person alone in a row to make them happy. However, if there are no remaining rows to seat them alone, we’ll have to seat them with someone from another family. This means the other person might no longer be happy since they are no longer seated alone.
The easiest way to handle part 2 is to check the number of remaining rows and people. If the number of remaining rows is greater than or equal to the number of unpaired people, all unpaired people can sit alone and remain happy. Otherwise, some people will have to share a row, and their happiness will be affected. In that case, the number of unhappy people will be 2 × remaining rows - remaining people
.
- Write down key observations and mix them to solve the problem
Problem B: Kar Salesman
Since no customer can buy more than one car from the same model, the minimum number of clients we need is determined by the model with the most cars. Therefore, we need at least: max(a_1, a_2, ..., a_n) clients, because even if a customer buys cars from other models, they cannot exceed this limit for any single model.
Each client can buy up to x
cars from different models. To distribute all the cars among the clients, we also need to consider the total number of cars. Thus, the minimum number of clients needed is at least: ceil((a_1 + a_2 + ... + a_n) / x). This ensures that all cars can be distributed across the clients, respecting the limit of x
cars per customer.
The actual number of clients required is the maximum of the two values: min_clients = max(ceil((a_1 + a_2 + ... + a_n) / x), max(a_1, a_2, ..., a_n)). This gives us a lower bound for the number of clients required, satisfying both constraints (the maximum cars of a single model and the total number of cars).
Apply binary search on the answer.
To demonstrate that this is always sufficient, we can reason that the most efficient strategy is to reduce the car count for the models with the largest numbers first. By doing so, we maximize the benefit of allowing each client to buy up to x
cars from different models.
After distributing the cars, two possible outcomes will arise: 1. All models will have the same number of remaining cars, and this situation will be optimal when the total cars are evenly distributed (matching the ceil((a_1 + a_2 + ... + a_n) / x) bound). 2. There will be still a quantity of models less than or equal to x remaining, which matches the case where the maximum number of cars from a single model max(a_1, a_2, ..., a_n)) determines the bound.
Imagine a grid of size w × x
, where w
represents the minimum number of clients needed: w=max(ceil((a_1 + a_2 + ... + a_n) / x), max(a_1, a_2, ..., a_n)) Now, place the cars in this grid by filling it column by column, from the first model to the n
-th model. This method ensures that each client will buy cars from different models and no client exceeds the x
car limit. Since the total number of cars is less than or equal to the size of the grid, this configuration guarantees that all cars will be sold within w
clients.
- If you don't know how to solve a problem, try to solve for small cases to find a pattern. -Don't trust too much in the constants, we decided to use a small x to encourage you to review small cases and find the pattern
Problem 3: Gerrymandering
We will use dynamic programming to keep track of the maximum number of votes Álvaro can secure as we move from column to column (note that there are many ways to implement the DP, we will use the easiest to understand).
An important observation is that if you use a horizontal piece in one row, you also have to use it in the other to avoid leaving holes.
Let dp[i][j]
represent the maximum number of votes Álvaro can get considering up to the i-th column. The second dimension j
represents the current configuration of filled cells:
j = 0
: All cells up to the i-th column are completely filled (including i-th). j = 1
: All cells up to the i-th column are completely filled (including i-th), and there’s one extra cell filled in the first row of the next column. j = 2
: The i-th column is filled, and there’s one extra cell filled in the second row of the next column.
For simplicity, we will call "L", "second L", "third L", and "fourth L" respectively the next pieces:
* ** ** *
** * * **
- From
dp[k][0]
(Both rows filled at column k): - You can place a horizontal piece in both rows, leading to
dp[k+3][0]
. - You can place a first L piece, leading to
dp[k+1][1]
- You can place an L piece, leading to
dp[k+1][2]
- From
dp[k][1]
(One extra cell in the first row of the next column): - You can place a horizontal piece in the first row occupying from k+2 to k+4 and also a horizontal piece in the second row from k+1 to k+3, leading to
dp[k+3][1]
. - You can place a fourth L, leading to
dp[k+2][0]
. - From
dp[k][2]
(One extra cell in the second row of the next column): - You can place a horizontal piece in the first row occupying from k+1 to k+3 and also a horizontal piece in the second row from k+2 to k+4, leading to
dp[k+3][2]
. - You can place a third L, leading to
dp[k+2][0]
.
More formally for each DP state, the following transitions are possible:
From dp[k][0]
: dp[k+3][0] = max(dp[k+3][0], dp[k][0] + vot) dp[k+1][1] = max(dp[k+1][1], dp[k][0] + vot) dp[k+1][2] = max(dp[k+1][2], dp[k][0] + vot)
From dp[k][1]
: dp[k+3][1] = max(dp[k+3][1], dp[k][1] + vot) dp[k+2][0] = max(dp[k+2][0], dp[k][1] + vot)
From dp[k][2]
: dp[k+3][2] = max(dp[k+3][2], dp[k][2] + vot) dp[k+2][0] = max(dp[k+2][0], dp[k][2] + vot)
To implement the DP solution, you only need to handle the transitions for states dp[i][0]
and dp[i][1]
. For dp[i][2]
, the transitions are the same as dp[i][1]
, with the rows swapped.
Not that there were more simple implementations, but we used this one to make it easier for you to understand :) 285746877
- Don't begin to implement until all the details are very clear, this will make your implementation much easier.
- Draw images to visualize easier everything.