fork download
  1. import sys
  2.  
  3. def solve():
  4. # 標準入力から全てのデータを読み込み、空白で分割
  5. input_tokens = sys.stdin.read().split()
  6. if not input_tokens:
  7. return
  8.  
  9. # ジョブの数 n
  10. n = int(input_tokens[0])
  11.  
  12. # ジョブ情報をリストに格納 [開始時刻, 終了時刻, 価値]
  13. jobs = []
  14. idx = 1
  15. for _ in range(n):
  16. s = int(input_tokens[idx])
  17. f = int(input_tokens[idx + 1])
  18. v = int(input_tokens[idx + 2])
  19. jobs.append([s, f, v])
  20. idx += 3
  21.  
  22. # 終了時刻(インデックス1)をキーに昇順で安定ソートを実行
  23. jobs.sort(key=lambda x: x[1])
  24.  
  25. # 添字を1から扱うため、先頭にダミー要素を追加
  26. # sorted_jobs[j] = [sj, fj, vj]
  27. sorted_jobs = [[-1, -1, 0]] + jobs
  28.  
  29. # 1. q(j) の計算(課題12aの処理)
  30. q = [0] * (n + 1)
  31. for j in range(1, n + 1):
  32. sj = sorted_jobs[j][0]
  33. # 線形探索で条件を満たす最大の i を探す
  34. for i in range(j - 1, 0, -1):
  35. if sorted_jobs[i][1] <= sj:
  36. q[j] = i
  37. break
  38.  
  39. # 2. OPT_j の計算(動的計画法)
  40. # opt[j] はジョブ 1 から j までを考慮したときの最大価値
  41. opt = [0] * (n + 1)
  42. for j in range(1, n + 1):
  43. vj = sorted_jobs[j][2]
  44. # 漸化式: OPT_j = max(v_j + OPT_{q(j)}, OPT_{j-1})
  45. include_j = vj + opt[q[j]]
  46. exclude_j = opt[j - 1]
  47.  
  48. if include_j > exclude_j:
  49. opt[j] = include_j
  50. else:
  51. opt[j] = exclude_j
  52.  
  53. # 指定された形式で出力
  54. for j in range(1, n + 1):
  55. print(f"opt {j} = {opt[j]}")
  56.  
  57. if __name__ == "__main__":
  58. solve()
Success #stdin #stdout 0.09s 14004KB
stdin
7
5 9 3
1 3 2
6 11 15
3 4 10
2 4 5
12 15 8
0 14 7
stdout
opt 1 = 2
opt 2 = 12
opt 3 = 12
opt 4 = 15
opt 5 = 27
opt 6 = 27
opt 7 = 35