🔹白色のカードに書き込む整数を $ x $ とする。 🔹青色のカードに書き込む整数を $ y $ とする。 🔹赤色のカードに書き込む数字は $ K - x - y $ となる。
この方法ですと3枚全部ではなく2枚の書き方のみを全探索するという解法が成り立ちます。
計算量は $ O(N^2) $ であり、十分に実行が可能です。
[Google Colaboratory]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
#--------- 入力例1 --------- N = 3# カードに記入できる数字の最大値 K = 6# 合計値 #--------- 入力例2 --------- # N = 3000 # カードに記入できる数字の最大値 # K = 4000 # 合計値 #--------------------------- Answer = 0 # 全探索 for x inrange(1, N + 1): for y inrange(1, N + 1): z = K - x - y if z >= 1and z <= N: Answer += 1
#--------- 入力例 ---------- N = 5 S = 7 A = [2, 1, 3, 8, 2] #--------------------------- # 動的計画法(i=0) dp = [[ None ] * (S + 1) for i inrange(N + 1)] dp[0][0] = True for i inrange(1, S + 1): dp[0][i] = False
# 動的計画法(i=1) for i inrange(1, N + 1): # カードの枚数分ループ for j inrange(0, S + 1): # 0から合計値Sまでループ if dp[i - 1][j] or (j - A[i - 1] > -1and dp[i - 1][j -A[i - 1]]): dp[i][j] = True else: dp[i][j] = False
# 答えの復元 Answer = [] Place = S for i inreversed(range(1, N + 1)): # 合計値Sから、1までループ(今回の場合:5,4,3,2,1) if dp[i - 1][Place]: Place = Place - 0# カード i を選ばない else: Place = Place - A[i - 1] # カード i を選ぶ Answer.append(i)
# 答えを出力(インデックスよりカードに書かれた数字を出力) print('解:', ' '.join(str(A[i - 1]) for i inreversed(Answer)))
#--------- 入力例1 --------- N = 3 S = 7 A = [2, 2, 3] #--------- 入力例2 --------- # N = 3 # S = 6 # A = [2, 2, 3] #--------------------------- # 動的計画法(i=0) dp = [[ None ] * (S + 1) for i inrange(N + 1)] dp[0][0] = True for i inrange(1, S + 1): dp[0][i] = False
# 動的計画法(i=1) for i inrange(1, N + 1): # カードの枚数分ループ for j inrange(0, S + 1): # 0から合計値Sまでループ if dp[i - 1][j] or (j - A[i - 1] > -1and dp[i - 1][j - A[i - 1]]): dp[i][j] = True else: dp[i][j] = False
# 答えの復元 # 変数 Place は現在位置(ゴールからスタート地点へ向かう) Answer = [] Place = N - 1 whileTrue: Answer.append(Place) print(Answer) if Place == 0: break
# どこから足場 Place に向かうのが最適かを求める if dp[Place - 1] + abs(H[Place - 1] - H[Place]) == dp[Place]: Place = Place - 1# 1つ前の足場に移動 else: Place = Place - 2# 2つ前の足場足場に移動
# 答えを出力(Answer[0]が足場1に対応) print('解:', ' → '.join(str(i + 1) for i inreversed(Answer)))