C - プロジェクトの選定 / Project Selection Editorial by admin
Claude 4.5 OpusOverview
This is a problem of selecting a combination of \(N\) projects that maximizes profit while avoiding conflicts and staying within budget. Given the constraint \(N \leq 18\), we examine all subsets using bit brute force.
Analysis
Key Insight
- The constraint \(N \leq 18\) is extremely important
- There are only \(2^N = 2^{18} = 262144\) possible selections
- This is small enough to allow exhaustive search
Why Bit Brute Force?
For each project, there are two choices: “select” or “don’t select”, so the selection state can be represented as an \(N\)-bit integer.
For example, when \(N = 4\):
- 0101 (= 5) → Select projects 1 and 3
- 1110 (= 14) → Select projects 2, 3, and 4
Checking Conflict Relations
Managing conflict relations with bitmasks is efficient.
Example: If project 0 conflicts with project 2, and project 0 conflicts with project 3:
- conflict[0] = 1100 (= 12) → Projects conflicting with 0 are 2 and 3
For a selected project \(i\), if mask & conflict[i] is non-zero, then a project conflicting with \(i\) is also selected, making it invalid.
Algorithm
Read Input: Read the cost and profit of each project, and the conflict relations
Convert Conflicts to Bitmasks: For each project \(i\), store the set of conflicting projects in
conflict[i]as a bitmaskEnumerate All Subsets: For each integer
maskfrom \(0\) to \(2^N - 1\):- The positions where bits are set in
maskrepresent selected projects - Check if there are no conflicts among selected projects
- Check if total cost is within budget \(K\)
- If both conditions are satisfied, calculate total profit and update the maximum
- The positions where bits are set in
Output Result: Output the maximum profit
mask = 0110 (Select projects 1, 2)
↓
For project 1: Check mask & conflict[1]
For project 2: Check mask & conflict[2]
↓
No conflicts & within budget → Calculate profit
Complexity
- Time Complexity: \(O(2^N \cdot N)\)
- For each of \(2^N\) subsets, check \(N\) projects
- When \(N = 18\), approximately \(262144 \times 18 \approx 4.7 \times 10^6\) operations
- Space Complexity: \(O(N)\)
- Size of the array
conflictstoring conflict relations
- Size of the array
Implementation Notes
Converting to 0-indexed: In the input, project numbers start from 1, so after reading \(U, V\), subtract 1 to make them 0-indexed
Basic Bit Operations:
mask & (1 << i): Check if the \(i\)-th bit ofmaskis setconflict[U] |= (1 << V): Set the \(V\)-th bit ofconflict[U]
Early Termination: When a conflict is found,
breakout of the loop to avoid unnecessary computationInitial Value: Since selecting nothing (
mask = 0) is also a valid choice, initializingmax_profitto 0 is fine
Source Code
def solve():
N, M, K = map(int, input().split())
projects = []
for i in range(N):
C, P = map(int, input().split())
projects.append((C, P))
# Manage conflict relations with bitmasks
conflict = [0] * N
for j in range(M):
U, V = map(int, input().split())
U -= 1 # 0-indexed
V -= 1
conflict[U] |= (1 << V)
conflict[V] |= (1 << U)
max_profit = 0
# Enumerate all subsets (2^N possibilities)
for mask in range(1 << N):
# Check if this subset satisfies conflict relations
valid = True
total_cost = 0
total_profit = 0
for i in range(N):
if mask & (1 << i):
# Project i is selected
# Check if any project conflicting with i is also selected
if mask & conflict[i]:
valid = False
break
total_cost += projects[i][0]
total_profit += projects[i][1]
if valid and total_cost <= K:
max_profit = max(max_profit, total_profit)
print(max_profit)
solve()
This editorial was generated by claude4.5opus.
posted:
last update: