Y2 CEP Test
Problem Analysis: Card Game, Love-Hate Relationship
Problem 1: Card Game
Summary
You are given 2 rows and N columns of integers, pick one integer from each column such that K of them lie in the upper column.
8
3
2
10
3
4
7
1
5
9
N = 5, K = 3
max sum = 36
Set One (1m)
Additional Limits: K = 0, N <= 15.
Solution: Since K = 0, all cards must be blue, therefore just sum up all blue cards.
8
3
2
10
3
4
7
1
5
9
N = 5, K = 0
max sum = 26
Set Two (1m)
Additional Limits: N <= 15.
Solution: There are at most 32 768 possibilities. Check all of them using recursion. Yay! :D
A Solution?
Possible Solution 1:
Pick the maximum K red cards first, then pick the remaining blue cards. Correct?
Possible Solution:
Pick the maximum K red cards first, then pick the remaining blue cards. Correct?
8
3
2
10
3
4
7
1
5
9
N = 5, K = 3
sum = 31
Possible Solution:
Pick the maximum K red cards first, then pick the remaining blue cards. Correct?
8
3
2
10
3
4
7
1
5
9
N = 5, K = 3
sum = 36
Therefore, this solution is incorrect.
Let's reduce the cases.
What if K = 1?
8
3
2
10
3
4
7
1
9
9
N = 5, K = 1
sum = ?
Let's reduce the cases.
What if K = 1?
8
3
2
10
3
4
7
1
9
9
N = 5, K = 1
sum = 34
Actual Solution:
What if we first assume all cards are first flipped blue?
8
3
2
10
3
4
7
1
9
9
N = 5, K = 3
sum = ?
Actual Solution:
We now want to "flip" three of these cards to red.
8
3
2
10
3
4
7
1
9
9
N = 5, K = 3
sum = 30
Actual Solution:
We now want to "flip" three of these cards to red.
8
3
2
10
3
4
7
1
9
9
N = 5, K = 3
sum = 36
+4
+1
+1
Actual Solution:
Therefore, we want to "flip" the K greatest values of "red minus blue".
8
3
2
10
3
4
7
1
9
9
N = 5, K = 3
sum = 36
+4
+1
+1
# Obtain N and K
first_line = input()
first_line = first_line.split(" ")
N = int(first_line[0])
K = int(first_line[1])
cards = []
# Obtain each card and dump into an array
for i in range(N):
line = input()
line = line.split(" ")
cards.append([int(line[0]), int(line[1])])
# Get sum of all blue sides
answer = 0
for i in range(N):
answer += cards[i][1]
differences = []
for i in range(N):
differences.append(cards[i][0] - cards[i][1])
# Sort the differences in order to get the highest K differences
differences.sort()
for i in range(N-K, N):
answer += differences[i]
print(answer)
Problem 2: Love-Hate Relationship
Summary
There are N students to be grouped into 2 classes. There are several conditions to fulfill: like pairs of students who must or must not be in the same class. How many ways do I have to split them?
Four students.
Student 1 and 2 must be in same class.
Student 3 and 4 must be in different class.
Total of 4 ways.
1
2
3
4
1
2
3
4
1
2
3
4
1
2
3
4
Let's break this problem down.
Simplified problem: Given the configurations of love-hate relationships, is any arrangement even possible at all?
A Simple Case
1
2
3
4
Student 1 hates Students 2 and 3.
Student 2 hates Students 1 and 3
Student 3 hates Students 1 and 2.
Student 4 hates Student 3.
A Simple Case
1
2
3
4
Student 1 hates Students 2 and 3.
Student 2 hates Students 1 and 3
Student 3 hates Students 1 and 2.
Student 4 hates Student 3.
A Simple Case
1
2
3
4
Student 1 hates Students 2 and 3.
Student 2 hates Students 1 and 3
Student 3 hates Students 1 and 2.
Student 4 hates Student 3.
A Simple Case
1
2
3
4
Student 2 hates Student 3.
Contradiction!
A Simple Case
1
2
3
4
Therefore, there are 0 ways to solve this.
If this case is detected, immediately output 0.
This case can be checked using recursion.
Slightly More Complexity
1
2
3
4
What if we assume that it is always possible?
Slightly More Complexity
1
2
3
4
Student 1 hates Student 2.
Student 2 hates Student 3.
Student 2 hates Student 4.
Slightly More Complexity
1
2
3
4
Student 1 hates Student 2.
Student 2 hates Student 3.
Student 2 hates Student 4.
Slightly More Complexity
1
2
3
4
Student 1 hates Student 2.
Student 2 hates Student 3.
Student 2 hates Student 4.
Slightly More Complexity
1
2
3
4
Student 1 hates Student 2.
Student 2 hates Student 3.
Student 2 hates Student 4.
Slightly More Complexity
1
2
3
4
1
2
3
4
Slightly More Complexity
Hypothesis: There are always two ways to group them.
True?
But... Sample Testcase?
What is the difference between this and the sample testcase that makes it have 2 ways instead of 4?
Let's look at the relationships.
Sample Testcase:
1 loves 2.
3 hates 4.
Current Case:
1 hates 2.
2 hates 3.
2 hates 4.
So what's the difference?
What if we draw it in a diagram?
Sample Testcase:
1 loves 2.
3 hates 4.
Current Case:
1 hates 2.
2 hates 3.
2 hates 4.
1 ---- 2
3 ---- 4
1 ---- 2 ---- 3
|
4
Observation:
1 ---- 2
3 ---- 4
1 ---- 2 ---- 3
|
4
For each "set" of connected people, I only have 2 ways to group them.
Actual Solution:
1. Use recursion to find out if there are any contradictions.
2a. If there are, output 0 immediately.
2b. If there are no contradictions, use recursion to find the number of "sets" given by the testcase.
3. Output 2^(number of sets)
# Recursive function to find class of students
def backtrack(student_id, class_id):
global fail
if fail:
return
if student_id in class_record:
# If a contradiction is detected, output 0. There is no way to group them.
if class_record[student_id] == class_id:
return
else:
fail = True
return
else:
class_record[student_id] = class_id
for relationship in relationships_from[student_id]:
# If a 'love' relationship exists, assign them to same class.
# Otherwise, assign them to different class.
if relationship[1] == 0:
backtrack(relationship[0], class_id)
else:
backtrack(relationship[0], (class_id + 1) % 2)
if fail:
return
# Obtain N and R
first_line = input()
first_line = first_line.split(" ")
N = int(first_line[0])
R = int(first_line[1])
# Obtain each relationship
relationships_from = []
for i in range(N):
relationships_from.append([])
for i in range(R):
line = input()
line = line.split(" ")
relationship_type = int(line[0])
person_a = int(line[1])
person_b = int(line[2])
# Zero index the persons to make it easier to manipulate
person_a -= 1
person_b -= 1
# Record the relationships
relationships_from[person_a].append([person_b, relationship_type])
relationships_from[person_b].append([person_a, relationship_type])
fail = False
total_sets = 0
class_record = {}
for i in range(N):
if not i in class_record:
backtrack(i, 0)
total_sets += 1
# If a contradiction has been detected, output 0.
if fail:
print(0)
else:
# Find the number of ways: 2^(the number of distinct sets)
total_ways = 1
for i in range(total_sets):
total_ways *= 2
print(total_ways)
Y2 CEP Test
By Pang Wen Yuen
Y2 CEP Test
- 503