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