0w1

Yuki 496 ワープクリスタル (給料日前編) ( DP )

No.496 ワープクリスタル (給料日前編) - yukicoder

題意:
你有 N 顆一次性的魔法石頭,第 i 顆可以幫你在 X 軸上 + X[ i ],Y 軸上 + Y[ i ],但花費魔力 C[ i ]。你現在在 ( 0, 0 ),你的目的地是 ( Gx, Gy )。另外一種移動方式是向上或向右一格,花費 F。問最少花費到達目的地。

制約:
0≤Gx,Gy≤100
0≤N≤50
1≤F≤200
0≤xi≤Gx, 0≤yi≤Gy, (xi,yi)≠(0,0)
1≤ci≤200

解法:
dp[ i ][ j ][ k ] : 已考慮前 i 顆石頭,現在在 ( j, k ),已形成的最小花費。
注意 N 可能為 0,這特判就行了。

時間 / 空間複雜度:
O( N * Gx * Gy )

from copy import deepcopy

Gx, Gy, N, F = map( int, input().split() )
X = []
Y = []
C = []
for i in range( N ):
  x, y, c = map( int, input().split() )
  X.append( x )
  Y.append( y )
  C.append( c )

if N == 0:
  exit( print( F * ( Gx + Gy ) ) )

INF = int( 1e15 )

dp = [ INF for i in range( Gy + 1 ) ]
dp = [ deepcopy( dp ) for i in range( Gx + 1 ) ]
dp = [ deepcopy( dp ) for i in range( N + 1 ) ]
dp[ 0 ][ 0 ][ 0 ] = 0
for i in range( N ):
  for j in range( Gx + 1 ):
    for k in range( Gy + 1 ):
      dp[ i + 1 ][ j ][ k ] = min( dp[ i + 1 ][ j ][ k ], dp[ i ][ j ][ k ] )
      if j + X[ i ] <= Gx and k + Y[ i ] <= Gy:
        dp[ i + 1 ][ j + X[ i ] ][ k + Y[ i ] ] = min( dp[ i + 1 ][ j + X[ i ] ][ k + Y[ i ] ], dp[ i ][ j ][ k ] + C[ i ] )
      if j + 1 <= Gx:
        dp[ i ][ j + 1 ][ k ] = min( dp[ i ][ j + 1 ][ k ], dp[ i ][ j ][ k ] + F )
        dp[ i + 1 ][ j + 1 ][ k ] = min( dp[ i + 1 ][ j + 1 ][ k ], dp[ i ][ j ][ k ] + F )
      if k + 1 <= Gy:
        dp[ i ][ j ][ k + 1 ] = min( dp[ i ][ j ][ k + 1 ], dp[ i ][ j ][ k ] + F )
        dp[ i + 1 ][ j ][ k + 1 ] = min( dp[ i + 1 ][ j ][ k + 1 ], dp[ i ][ j ][ k ] + F )

print( dp[ N ][ Gx ][ Gy ] )