This is one of the problems from the 2015 ICPC NorthWest Programming Contest and I was wondering if there is any easier or more efficient way of doing it.
Here's the problem:
"Fred likes to wear mismatched socks. This sometimes means he has to plan ahead.
Suppose his sock drawer has one red, one blue, and two green socks. If he wears the
red with the blue, he's stuck with matching green socks. He put together two
mismatched pairs if he pairs red with green and then blue with green. Given the
contents of his sock drawer, how many pairs of mismatched socks can he put together?"
Here's a sample input:
Color 1 -> 4 socks
Color 2 -> 3 socks
Color 3 -> 7 socks
Color 4 -> 11 socks
Color 5 -> 4 socks
The way I'm doing is I first read the input into an array and sort it increasingly. That way I'll have the highest number of socks at the end of the array. From here I basically compare arr[i] and arr[i-1] and get the min between them. Add that to the total, save the remainder and just repeat the process going down the array. For example, using the sample input it looks something like this:
Sorted array: [3,4,4,7,11]
1:3 socks ---> 1:3 socks ---> 1:0 socks ---> 1:0 socks
2:4 socks ---> 2:4 socks ---> 2:1 socks ---> 2:1 socks
3:4 socks ---> 3:4 socks ---> 3:0 socks ---> 3:0 socks
4:7 socks ---> 4:0 socks ---> 4:0 socks ---> 4:0 socks
5:11 socks ---> 5:4 socks ---> 5:0 socks ---> 5:0 socks
------> total = 14 possible combinations of mismatched socks. This seems way too naive an approach. Does anyone have any ideas on how to optimize it ? I can post my code for this if necessary.
I think the optimal solution can be found by examining all possible groupings of the different sock colors into 2 piles. For each such grouping p odd pairs of socks can be made, where p is the number of socks in the smallest pile. You want the grouping that gives the maximum p. You can generate all possible groupings of socks into 2 piles recursively.
Here's some Java code to illustrate:
public static void main(String[] args)
{
int[] socks = {3,4,4,7,11};
System.out.println(count(0, 0, socks, 0));
}
static int count(int a, int b, int[] socks, int i)
{
if(i == socks.length)
{
return Math.min(a, b);
}
return Math.max(count(a+socks[i], b, socks, i+1),
count(a, b+socks[i], socks, i+1));
}
Output:
14
Build a graph data structure. Every sock is vertex. Make edges from every vertex to all vertices of another color.
Now find power of maximum matching - size of the set of edges without common vertices.
You can build max matching using Edmonds algorithm in polynomial time O(V^2*E). Seems that graph for this task would be dense, so complexity tends to O(V^4). There exists also Micali and Vazirani algorithm with lesser complexity (don't know about implementation hardness).
If your task doesn't require max matching itself - only number of edges, then that value might be calculated using randomized Lovasz algorithm based on Tutte's matrix theorem. (I did not find concise English description - perhaps terms might differ, short one in Russian is here)
"HOPEFULLY CORRECT THIS TIME!" METHOD
Step 1: Check if there's 2 or more colours left. If there's none or one colour left you're finished (can't find more pairs).
Step 2: Find one colour that has the lowest non-zero count
Step 3: Excluding the colour with the lowest count (in case all colours have the same count); find the highest count and determine how many colours share the highest count
Step 4: Excluding the colour with the lowest count and all colours with the highest count; try to find the second highest count.
Step 5a: If there is a second highest count, calculate amount_to_pair = min(highest_count - second_highest_count, lowest_count).
Step 5b: If there isn't a second highest count, calculate amount_to_pair = lowest_count.
Step 6: Create amount_to_pair pairs by pairing socks from the colour with the lowest count with socks with colours that have the highest count as evenly as possible (e.g. if there's 9 red socks, 20 blue socks and 20 green socks; then create 5 "red and blue" pairs and 4 "red and green" pairs).
Step 7: Goto step 1.
Example (the pathological case mentioned in comments):
Initial condition
Color 1 -> 1 socks
Color 2 -> 20 socks
Color 3 -> 80 socks
Color 4 -> 81 socks
First iteration:
Color 1 -> 1 socks (lowest non-zero count)
Color 2 -> 20 socks
Color 3 -> 80 socks (2nd highest count)
Color 4 -> 81 socks (highest count)
Amount to remove = min(81-80, 1) = 1
Color 1 -> 1-1=0 socks (lowest non-zero count)
Color 2 -> 20 socks
Color 3 -> 80 socks
Color 4 -> 81-1=80 socks (highest count)
Results so far:
(1 pair of colour 1 and colour 4)
Second iteration:
Color 1 -> 0 socks
Color 2 -> 20 socks (lowest non-zero count)
Color 3 -> 80 socks (highest count)
Color 4 -> 80 socks (highest count)
Amount to remove = 20
Color 1 -> 0 socks
Color 2 -> 20-20=0 socks (lowest non-zero count)
Color 3 -> 80-(20/2)=70 socks (highest count)
Color 4 -> 80-(20-20/2)=70 socks (highest count)
Results so far:
(1 of colour 1 and colour 4)
(10 of colour 2 and colour 3)
(10 of colour 2 and colour 4)
Third iteration:
Color 1 -> 0 socks
Color 2 -> 0 socks
Color 3 -> 70 socks (lowest non-zero count)
Color 4 -> 70 socks (highest count)
Amount to remove = 70
Color 1 -> 0 socks
Color 2 -> 0 socks
Color 3 -> 70-70=0 socks (lowest non-zero count)
Color 4 -> 70-70=0 socks (highest count)
Results so far:
(1 of colour 1 and colour 4)
(10 of colour 2 and colour 3)
(10 of colour 2 and colour 4)
(70 of colour 3 and colour 4)
ORIGINAL METHOD
WARNING: The method below gives wrong results in various pathological cases (and has been updated/replaced by the algorithm above). I've left it here to give context to some of the comments
Starting condition:
Color 1 -> 4 socks
Color 2 -> 3 socks
Color 3 -> 7 socks
Color 4 -> 11 socks
Color 5 -> 4 socks
Find the highest count and lowest count; and cancel out whichever has lowest count so it ceases to exist:
Color 1 -> 4 socks
Color 3 -> 7 socks
Color 4 -> 11-3=8 socks
Color 5 -> 4 socks
Results so far:
(3 of colour 2 and colour 4)
Do it again:
Color 3 -> 7 socks
Color 4 -> 8-4=4 socks
Color 5 -> 4 socks
Results so far:
(3 of colour 2 and colour 4)
(4 of colour 1 and colour 4)
Do it again:
Color 3 -> 7-4=3 socks
Color 5 -> 4 socks
Results so far:
(3 of colour 2 and colour 4)
(4 of colour 1 and colour 4)
(4 of colour 4 and colour 3)
Do it again:
Color 5 -> 4-3=1 sock
Results so far:
(3 of colour 2 and colour 4)
(4 of colour 1 and colour 4)
(4 of colour 4 and colour 3)
(4 of colour 3 and colour 5)
Stop because there's only one colour left.
Related
I have a problem where I have a N x 3 matrix with int values. I need to tile it with K 2x1 or 1x2 tiles so that they do not overlap and that I get the maximum sum with the use of dynamic programming.
What would the best way be to solve such a problem?
Example 5 x 3 matrix, K = 5:
2 6 2
6 5 6
2 6 2
1 1 1
1 1 1
Good tiles: (6,2), (6,2), (6,2), (6,5), (2,1)
Result = 38
And an example with an edge case:
2 x 3 Matrix, K = 2
0 4 1
3 4 1
Good tiles: (4,1), (4,3)
Result = 12
Let's define the state of a row as the cells that are covered by some of the K bricks. You have 8 combinations (2^3) from 000 (everything is not covered) to 111 (everything is covered) (you can use binary to encode the state for efficiency).
The dynamic programming matrix will be a[row][tiles][state]. Where row is the row we are processing, going top to bottom, tiles is how many tiles you placed already, state is the state as we defined above and the value is the current maximum sum.
To fill it we go top to bottom. We simplify things by only allowing a vertical tile to be placed on the current and the row above (not below). You can iterate through tile placement combinations between the rows (some are mutually exclusive). You have 3 vertical options and 2 horizontal options on the current row (5 options, for a total of 12 combinations, if I've done the math right). Also iterate through the possible values of 'titles'. For each combination look for all possible combination that allow it's placement on the previous row (so that the vertical tiles don't overlap) take the maximum and update the dynamic matrix. Some combinations are very strict (3 vertical tiles require 000 in the row above), while some are very relaxed (1 horizontal tile allows for every posibility). Do this on paper a few times to see how it works.
As an optimization note that you only need to know the values from the previous row, as the ones above that don't factor into so you can keep only the previous row and current row.
Algorithm should look something like this
For i from 0 to N
for tiles from 0 to K
for each combination
if tiles - combination.tiles < 0: continue
m = -1
for each state compatible with combination.previous_row
m = max(m, a[i-1][tiles - combination.tiles][state])
if m > 0
a[i][tiles][combination.state] = max(a[i][tiles][combination.state], m)
The solution is the maximum between the states on last row with tiles=K.
Complexity will be N*K* 12 combinations * 2^3 states so O(N*K). Memory can be O(K) with the trick I've mentioned above.
Good morning,
Imagine a list of many bags (100).
Each bag can be color=red/yellow/green, size=small/big, heavy=yes/no, woolmade=yes/no
I want to select P=10 numbers of bags that satisfies these conditions:
A=3 number of red bags
B=5 number of small bags
C=2 number of heavy=yes bags
D=3 number of woolmade=yes bags
Here is a concrete example (simplified to 2 attributes):
List of 10 bags (id, color, woolmade Y/N):
(1, red, Y), (2, red, Y), (3, red, Y), (4, red, Y), (5, red, N), (6, green, N), (7, green, N),(8, green, N), (9, green, N), (10, green, Y)
I want to get 5 bags with 3 of red and 4 of woolmade=Y
One possible answer are IDs: 1, 2, 3, 9 & 10
The following answer is NOT correct: IDs 1, 2, 3, 5 & 10 because I will have 4 of red (I only want 3 of red) and 4 of woolmade=Y (correct)
I am interested in a algorithm explanation and a possibly implementation (nodes, java, python, vba, ...)
Thanks
Brute Force:
I just thought about, how to search in all possible combinations for the right ones.
There are 24 different kinds of bags so there are 24 ^ 10 possible combinations.
These can be generated like numbers to root 24 simply by incrementing these.
Each number can be checked according to your criteria.
If the checking of one combinations needs 1 microsecond, about 17612 hours are necessary to check all combinations.
Using only one thread, in about 2 years you might find all possible combinations that fit your criteria.
Backtracking:
If you stop at the first combination of 10 bags that works out, you implemented a backtracking algorithm. How long this might last I can't calculate right now.
Better Brute Force:
Looking at the example below, you see that not all numbers to base 24 are interesting. The problem can be solved by looking at all combinations of 10 elements of numbers between 0 and 23 which may repeat themselves and check these elements. There are 92561040 possible combinations. The check of those may last about 92 seconds. Afterward you will have all possible combinations which solve your problem, if you stop at the first combination you might be much faster.
Example
to understand the 10 numbers see the bag mapping below.
0000000000 10 red, 10 small, 10 heavy, 10 wool
0000000001 9 red, 1 yellow, 10 small, 10 heavy, 10 wool
0000000002 9 red, 1 green, 10 small, 10 heavy, 10 wool
...
000000000A 9 red, 1 yellow, 9 small, 1 big, 9 heavy, 1 small, 10 wool
000000000B 9 red, 1 green, 9 small, 1 big, 9 heavy, 1 small, 10 wool
...
as you can see, for the result, it is only important the name of the same digits, not the place. therefore the number of interesting combinations are not all numbers to the base 24 with 10 places, but all combinations of 10 numbers between 0 and 23 which may be repeated:
(24 + 10 - 1)!/((24 - 1)!10!) = 92561040 combinations which may be checked in 92 seconds if each check need 1 microsecond.
Mapping:
red/small/yes/yes = 0
yellow/small/yes/yes = 1
green/small/yes/yes = 2
red/big/yes/yes = 3
yellow/big/yes/yes = 4
green/big/yes/yes = 5
red/small/no/yes = 6
yellow/small/no/yes = 7
green/small/no/yes = 8
red/big/no/yes = 9
yellow/big/no/yes = A
green/big/no/yes = B
red/small/yes/no = C
yellow/small/yes/no = D
green/small/yes/no = E
red/big/yes/no = F
yellow/big/yes/no = G
green/big/yes/no = H
red/small/no/no = I
yellow/small/no/no = J
green/small/no/no = K
red/big/no/no = L
yellow/big/no/no = M
green/big/no/no = N
lets say, we have two cubes of 3X3 with different heights in cell. Each cell value represents the height of that cell. For example in below block 1, cell (1,1) has height of 1, cell(1,2) has height of 2 and so on.
block-1,
1 2 3
1 3 2
3 1 2
block-2,
4 3 2
4 2 3
2 4 3
Giver two such blocks how to check efficiently whether two blocks can be connected in such a way that there would be no cell mismatched and both blocks together produce a cuboid.
For example, above block-1 + block-2 can be connected and resultant block will be a perfect cuboid height 5. Resultant cuboid will be,
5 5 5
5 5 5
5 5 5
Extension of the problem: Given a set (size >= 50K) of such 4X4 blocks how to connect pair of blocks and produce maximum height sum of resultant cuboid? You can take only matched blocks full height to maximise total height sum. Non matched blocks will be ignored. Each cell height can be up to 20 unit.
Further extension of the problem: Blocks can be given in such a way that might be rotated to make pair with other to maximise resultant cuboids height sum.
Any clue?
You could solve the problem in two steps (1) find all pairs of blocks that connect (build a cuboid) and (2) find the best pairing that maximizes the total height.
Find connecting pairs
For this I would (a) build a surface representation for each block, (b) hash the blocks by their surface representation and (c) search for each block all connecting blocks by looking for the connecting surface models.
(a) Building the surface model
The basic idea is to represent each block by its surface. For this you just subtract the minimum entry in the matrix from every entry in the matrix
surface representation of block-1 will be
1 2 3 -1 0 1 2
1 3 2 --> 0 2 1
3 1 2 2 0 2
and surface representation of block-2 will be
4 3 2 -2 2 1 0
4 2 3 --> 2 0 1
2 4 3 0 2 1
(b) hash the blocks
Now you hash the blocks by their surface representation
(c) Finding connecting pairs
For each block you then compute the connecting surface model, by taking the maximum value in the surface representation and subtracting the entries in the matrix from it,
for block-1 this will yield
0 1 2 2 1 0
2 - 0 2 1 = 2 0 1
2 0 2 0 2 0
the blocks with this surface representation can be found using the hash table (note that the surface representation of block-2 will match).
Note: when you allow for rotation then you will have to perform 4 queries on the hash table with all possible rotations.
Finding the best pairing
To find the best pairing (maximizing the sum of connected blocks) I would use the Hungarian Algorithm. In order to do this you will have to build a matrix where the entry (i, j) contains the height of the block when the two blocks i and j connect and 0 otherwise.
Edit
I think the second step (finding best pairing) can be done more efficiently, by connecting pairs of matching blocks greedily (connecting pairs resulting in highest blocks first).
The intuition for this is: When you have two blocks a and b and they both have the same surface model. Then they will either both connect to another block c or they both won't connect to c. With this in mind, after the "find connecting pairs" step you will end up with pairs of groups of blocks (Xi, Yi) where each block of Xi connects to each block of Yi. If the two groups Xi and Yi are of equal size, then we can connect in any way we want and will always get the same sum of height of resulting cuboids. If one of the groups (wlog Yi) contains less elements then we want to avoid connecting to the smallest blocks in Xi. Thus we can greedily connect starting with the largest blocks and in doing so avoid connecting to the smallest blocks.
So the algorithm could work as follows:
(Hash each block according to its surface representation. Sort
blocks with the same surface representation descending according to
their offset (height of block minus surface representation)
Process blocks in order of descending offset, for each block: Search
for connecting block cBlock with highest offset, connect the two
blocks, remove cBlock from the hash table and the processing
pipeline.
Overall this should be doable in O(n log n)
Given a rectangle consisting of 1's and 0's, how can I find the maximum number of non-overlapping 2x2 squares of 1's?
Example:
0110
1111
1111
The solution would be 2.
I know it can be solved with Bitmask DP; but I can't really grasp it - after playing with it for hours. How does it work and how can it be formalised?
I wanted to point out that the graph we get by putting vertices at the centers of squares and joining them when they overlap is not claw-free:
If we take (in the full plane) a 2x2 square and three of the four diagonally overlapping 2x2 squares, they form the induced subgraph
• •
\ /
•
/
•
This is a claw, meaning that any region containing those squares corresponds to a non-claw-free graph.
If you build a graph where every node represents a 2x2 square of 1's and there is an edge between two nodes if they overlap, then the problem is now: find the maximum independent set in this graph.
Here is a dynamic programming solution.
The state is (row number, mask of occupied cells, shift position). It looks like this:
..#..
.##..
.#...
.#...
In this case, the row number is 2(I use zero-bases indices), the mask depends on whether we take a cell with # or not, the shift position is 1. The number of states is O(n * m * 2 ^ n). The value of a state is the maximum number of picked 2x2 squares. The base case is f(1, 0, 0) = 0(it corresponds to the first row and no 2x2 squares picked so far).
The transitions are as follows:
..#.. ..#..
.00.. -> ..1..
.0... .11..
.#... .#...
This one can be used if and only if the square consists of ones in the original matrix and there were zeros in the mask(it means that we pick this square).
The other one is:
..#.. ..#..
.##.. -> ..#..
.#... .#0..
.#... .#...
This one is always applicable. It means that we do pick this 2x2 square.
When we are done with one row, we can proceed to the next one:
..#.. ..#0.
..#.. -> ..#..
..#.. ..#..
.##.. ..#..
There are at most two transitions from each state, so the total time complexity is O(n * m * 2 ^ n). The answer the maximum among all masks and shifts for the last row.
edit 20:18, there is a counterexample posted by #ILoveCoding
My intuition says, that this will work. I am unable to prove it since I'm not advanced enough. I can't think of any counterexample though.
I will try describe the solution and post the code, please correct me if my solution is wrong.
First we load input to an array.
Then we create second array of the same size and for every possible placing of 2x2 square we mark 1 in the second array. For the example posted by OP this would look like below.
0 1 0 0
1 1 1 0
0 0 0 0
Then for every 1 in second array we calculate the number of neighbours (including diagonals) + 1 (because if it doesn't have any neighbours we have to still see it as 1). We set those new numbers to the array. Now it should look like this.
0 4 0 0
3 4 3 0
0 0 0 0
Then for every non-zero value in the array we check whether it has any neighbour with bigger or equal value. If it has then move on since it can't be in the solution.
If we don't find any such value then it will be in the solution. We have to reset to zero every neighbour of the original value (because it can't be in the solution, it would overlap the solution.
So the first such number found should be 2 on the left. After processing it the array should look like following.
0 0 0 0
3 0 3 0
0 0 0 0
When we check the other 3 situation is the same.
We end up with non-zero values in the array indicating where top left corners of 2x2 squares are.
If you need the numer of them just traverse the array and count non-zero elements.
Another example
1111 -> 1 1 1 0 -> 4 6 4 0 -> 4 0 4 0
1111 -> 1 1 1 0 -> 6 9 6 0 -> 0 0 0 0
1111 -> 1 1 1 0 -> 6 9 6 0 -> 6 0 6 0
1111 -> 1 1 1 0 -> 6 9 6 0 -> 0 0 0 0
1111 -> 1 1 1 0 -> 4 6 4 0 -> 4 0 4 0
1111 -> 0 0 0 0 -> 0 0 0 0 -> 0 0 0 0
The code I write can be found here
http://ideone.com/Wq1xRo
I have to find which of the following values can be the degrees of an undirected graph with 6 vertices:
a) 3 2 2 2 3 3
b) 4 2 2 2 3 2
c) 5 2 2 2 0 3
d) 5 2 2 2 1 2
I only method I found is to try to draw the graph on a sheet of paper and then check if it is possible.
I just need a hint to start this problem, if possible, in other way than drawing each graph.
The following algorithm decides if a simple graph can be constructed with given node degrees:
sort the degrees in descending order
if the first degree is 0 (i.e.all degrees are 0) then obviously such a graph can be formed (no edges) and you are done.
if the first degree has value d (> 0) then the following d degrees must be greater 0. If not you are done: no such graph can be formed.
take away the first degree (value d) and reduce the following d degrees by one (i.e. draw the requested number of edges from the node with highest degree to the nodes with highest degrees among the remaining ones - see proof below for correctness of this assumption), then continue with step 1 (with now one node less)
example a) (can be rejected because of the odd sum of weights, but also the above algorithms works)
3 2 2 2 3 3
3 3 3 2 2 2
2 2 1 2 2
2 2 2 2 1
1 1 2 1
2 1 1 1
0 0 1
1 0 0
-1 not possible
example c)
5 2 2 2 0 3
5 3 2 2 2 0
2 1 1 1 -1 not possible
example d)
5 2 2 2 1 2
5 2 2 2 2 1
1 1 1 1 0
0 1 1 0
1 1 0 0
0 0 0 ok
What is missing is a proof that if a graph can be drawn with given node degrees, then one of the matching graphs has this property of step 4, i.e. that the node with highest degree is connected with the nodes with next highest degrees.
Let us therefore assume that A is the node with highest degree and that it is connected with a node B whose degree is less then the degree of node C not being connected to A. Since degree(C) > degree(B), there is node D connected to C and not connected to B. Thus, there are edges AB and CD, and there are no edges AC nor BD. So we can replace AB and CD by the edges AC and BD without changing the nodes' degrees.
By repeating this procedure enough times we can make all nodes with the next highest degrees being connected to node with the highest degree.
The handshaking lemma or degree sum formula is necessary and sufficient condition in this case, since we only care that it forms an undirected graph (orientation of the edge doesn't matter, but nothing is said about loop or parallel edges). Therefore, option c and option d are valid 6-vertex undirected graph.
If the question asks for simple undirected graph (loop and parallel edges disallowed), then we need to bring in the algorithm by Havel/Hakimi, which is as described by #coproc.