aacord’s memo

abcを中心にpythonで解いた問題のメモ、整理をしています。緑になった。

abc 162 f(python)

解説AC。文字列の偶数番目と奇数番目で条件をかえながら dp を作った。
文字列の長さが奇数のときは、2つ飛ばしを2回まで、または3つ飛ばしを一回まで使うことができる。
よって dp[i][[j] を i = i 番目の数字、
i が偶数なら
j = 0(もう一つ飛ばししかできない)
j = 1(2つ飛ばしを一回使える)
j = 2(2つ飛ばしを2回、または3つ飛ばしを1回使える)

i が奇数なら
j = 2 (2つ飛ばしを一回使える)
j = 1(もう一つ飛ばししかできない)

ときめて dp を作った。
3つ飛ばしを考慮する時点で n<=3までは別に考える必要があること、文字列の長さが奇数のときは
dp[n-1][2] が数字を (n+1)//2 個含んでいるので、両端のうちの小さいほうを引く必要があることなど、
ぐちゃぐちゃな式となってしまった

import sys
input = sys.stdin.readline
n = int(input())
a = [int(i) for i in input().split()]
if n <= 3:
  print(max(a))
  exit()

a = tuple(a)
dp = [[-10**15]*3 for i in range(n)]

dp[0][2] = a[0]
dp[1][2] = a[1]
dp[2][2] = a[0]+a[2]
dp[3][2] = max(a[0],a[1])+a[3]
dp[3][1] = a[0]+a[3]
for i in range(2,n-2):
  if i%2 == 0:
    dp[i+2][2] = dp[i][2]+a[i+2]
    dp[i+2][0] = max(dp[i][0]+a[i+2],dp[i-1][1]+a[i+2],dp[i-2][2]+a[i+2])
  else:
    dp[i+2][2] = max(dp[i][2],dp[i][1],dp[i-1][2])+a[i+2]
  dp[i+2][1] = max(dp[i][1]+a[i+2],dp[i-1][2]+a[i+2])
if n%2 == 1:
  c = min(a[0],a[-1])
  dp[n-1][2] -= c
print(max(dp[n-1][0],dp[n-1][1],dp[n-1][2]))

追記:一応after_contestも通っていた