結果

問題 No.733 分身並列コーディング
ユーザー qwewe
提出日時 2025-05-14 13:14:50
言語 PyPy3
(7.3.15)
結果
AC  
実行時間 136 ms / 1,500 ms
コード長 6,054 bytes
コンパイル時間 337 ms
コンパイル使用メモリ 82,700 KB
実行使用メモリ 80,552 KB
最終ジャッジ日時 2025-05-14 13:15:54
合計ジャッジ時間 6,261 ms
ジャッジサーバーID
(参考情報)
judge2 / judge4
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 3
other AC * 46
権限があれば一括ダウンロードができます

ソースコード

diff #

import sys

# Read input faster for competitive programming
input = sys.stdin.readline

def solve():
    # Read the time limit T
    T = int(input())
    # Read the number of problems N
    N = int(input())
    # Read the time required for each problem t_i
    # Store them in a list t
    t = [int(input()) for _ in range(N)]

    # Use float('inf') as a representation for infinity. This will be used for unreachable states
    # or states not yet optimally determined.
    INF = float('inf')
    
    # Initialize DP tables. We use two arrays:
    # dp_people[mask] stores the minimum number of people required to complete the subset of problems represented by 'mask'.
    # dp_time[mask] stores the minimum time used by the *last* person assigned tasks among those minimum people.
    # The size of the DP table is 2^N, covering all possible subsets of N problems.
    dp_people = [INF] * (1 << N)
    dp_time = [INF] * (1 << N)

    # Base case: To solve 0 problems (mask 0), we conceptually start with 1 person available,
    # who has currently used 0 time. This sets up the start of the DP process.
    dp_people[0] = 1
    dp_time[0] = 0

    # Iterate through all possible subsets of problems, represented by masks from 0 to 2^N - 1.
    # The order ensures that when we compute dp for 'mask', the dp values for all smaller masks (subsets) are already computed.
    for mask in range(1 << N):
        # If the current state 'mask' is unreachable (dp_people[mask] is still INF),
        # it means this subset cannot be formed based on previous states, so we skip it.
        if dp_people[mask] == INF: 
            continue
        
        # Get the current optimal state for 'mask'
        current_people = dp_people[mask]
        current_last_time = dp_time[mask]
        
        # Iterate through each problem index 'i' from 0 to N-1.
        for i in range(N):
            # Check if problem 'i' is NOT already included in the current subset 'mask'.
            # This is done by checking if the i-th bit of 'mask' is 0.
            if not (mask & (1 << i)):
                # If problem 'i' is not in 'mask', we can potentially add it.
                # The new mask representing the subset including problem 'i' is 'next_mask'.
                next_mask = mask | (1 << i) 
                
                # --- Try Option 1: Assign problem 'i' to the current last person ---
                # This is only possible if adding task 'i' does not exceed the time limit T for this person.
                if current_last_time + t[i] <= T:
                    # If valid, calculate the potential new state: same number of people, updated time for the last person.
                    proposed_people1 = current_people
                    proposed_time1 = current_last_time + t[i]
                    
                    # Compare this potential state with the current best state recorded for 'next_mask'.
                    # Check if the proposed state is better (fewer people, or same people with less time for the last one).
                    current_best_people = dp_people[next_mask]
                    current_best_time = dp_time[next_mask]
                    
                    is_proposed1_better = False
                    if current_best_people == INF: # If next_mask hasn't been reached optimally yet, any valid state is better.
                        is_proposed1_better = True
                    elif proposed_people1 < current_best_people: # Fewer people is always better.
                        is_proposed1_better = True
                    elif proposed_people1 == current_best_people and proposed_time1 < current_best_time: # Same people, less time is better.
                        is_proposed1_better = True

                    # If the proposed state is indeed better, update the DP table for 'next_mask'.
                    if is_proposed1_better:
                         dp_people[next_mask] = proposed_people1
                         dp_time[next_mask] = proposed_time1

                # --- Try Option 2: Assign problem 'i' to a new person ---
                # This option is always available (assuming problem constraints t[i] <= T).
                # It increases the total number of people by 1.
                # The new person starts with task 'i', taking t[i] time. This person becomes the new 'last person'.
                proposed_people2 = current_people + 1
                proposed_time2 = t[i] 

                # Compare this potential state with the current best state recorded for 'next_mask'.
                # IMPORTANT: Read the current best state for 'next_mask' again, as it might have been updated by Option 1 just above.
                current_best_people = dp_people[next_mask] 
                current_best_time = dp_time[next_mask]
                
                is_proposed2_better = False
                if current_best_people == INF: # If next_mask hasn't been reached optimally yet, any valid state is better.
                     is_proposed2_better = True
                elif proposed_people2 < current_best_people: # Fewer people is always better.
                     is_proposed2_better = True
                elif proposed_people2 == current_best_people and proposed_time2 < current_best_time: # Same people, less time is better.
                     is_proposed2_better = True

                # If the proposed state is indeed better, update the DP table for 'next_mask'.
                if is_proposed2_better:
                     dp_people[next_mask] = proposed_people2
                     dp_time[next_mask] = proposed_time2

    # After iterating through all masks, the DP table is filled.
    # The final answer is the minimum number of people required to complete all N problems.
    # This is stored in the DP state corresponding to the mask where all bits are set (1<<N) - 1.
    final_mask = (1 << N) - 1
    # Print the minimum number of people required.
    print(dp_people[final_mask])

# Call the main function to solve the problem
solve()
0