많은 수의 하위 문제가있는 동적 프로그래밍. 그래서 인터뷰 거리 에서이 문제를 해결하려고합니다.
그리드 워킹 (50 점 점수)
당신은에 위치하고 있습니다 위치에 차원 그리드 . 격자의 치수는 )입니다. 한 단계에서 차원 중 하나에서 한 단계 앞뒤로 걸을 수 있습니다 . (그래서 항상 거기에 가능한 다른 이동). 얼마나 많은 방법으로 M 을 취할 수 있습니까어떤 시점에서 그리드를 떠나지 않도록 단계? , 또는 경우 그리드를 떠납니다 .
내 첫 번째 시도는이 메모 된 재귀 솔루션이었습니다.
def number_of_ways(steps, starting_point):
global n, dimensions, mem
#print steps, starting_point
if (steps, tuple(starting_point)) in mem:
return mem[(steps, tuple(starting_point))]
val = 0
if steps == 0:
val = 1
else:
for i in range(0, n):
tuple_copy = starting_point[:]
tuple_copy[i] += 1
if tuple_copy[i] <= dimensions[i]:
val += number_of_ways(steps - 1, tuple_copy)
tuple_copy = starting_point[:]
tuple_copy[i] -= 1
if tuple_copy[i] > 0:
val += number_of_ways(steps - 1, tuple_copy)
mem[(steps, tuple(starting_point))] = val
return val
큰 놀라움 : 메모리 부족으로 인해 많은 단계 및 / 또는 차원에서 실패합니다.
다음 단계는 동적 프로그래밍을 사용하여 솔루션을 개선하는 것입니다. 그러나 시작하기 전에 접근 방식에 큰 문제가 있습니다. 인수 starting_point
는 튜플이며, 여기서 은 입니다. 그래서 사실, 기능 수 number_of_ways(steps, x1, x2, x3, ... x10)
와 .
교과서에서 본 동적 프로그래밍 문제에는 거의 모두 twp 변수가 있으므로 2 차원 행렬 만 필요합니다. 이 경우 10 차원 매트릭스가 필요합니다. 그래서 총 세포.
최신 정보
Peter Shor의 제안을 사용하고, 약간의 수정, 특히 함수 에서 위치를 추적 하고 치수를 두 세트 A와 B로만 분할하는 것이 아니라 재귀 적으로 효과적으로 분할을 수행 해야 할 필요성 한 세트의 차원 만있는 기본 사례에 도달 할 때까지 분할 및 정복 방법.
다음 구현을 생각해 냈습니다.이 테스트는 최대 실행 시간 미만의 모든 테스트를 통과했습니다.
def ways(di, offset, steps):
global mem, dimensions
if steps in mem[di] and offset in mem[di][steps]:
return mem[di][steps][offset]
val = 0
if steps == 0:
val = 1
else:
if offset - 1 >= 1:
val += ways(di, offset - 1, steps - 1)
if offset + 1 <= dimensions[di]:
val += ways(di, offset + 1, steps - 1)
mem[di][steps][offset] = val
return val
def set_ways(left, right, steps):
# must create t1, t2, t3 .. ti for steps
global mem_set, mem, starting_point
#print left, right
#sleep(2)
if (left, right) in mem_set and steps in mem_set[(left, right)]:
return mem_set[(left, right)][steps]
if right - left == 1:
#print 'getting steps for', left, steps, starting_point[left]
#print 'got ', mem[left][steps][starting_point[left]], 'steps'
return mem[left][steps][starting_point[left]]
#return ways(left, starting_point[left], steps)
val = 0
split_point = left + (right - left) / 2
for i in xrange(steps + 1):
t1 = i
t2 = steps - i
mix_factor = fact[steps] / (fact[t1] * fact[t2])
#print "mix_factor = %d, dimension: %d - %d steps, dimension %d - %d steps" % (mix_factor, left, t1, split_point, t2)
val += mix_factor * set_ways(left, split_point, t1) * set_ways(split_point, right, t2)
mem_set[(left, right)][steps] = val
return val
import sys
from time import sleep, time
fact = {}
fact[0] = 1
start = time()
accum = 1
for k in xrange(1, 300+1):
accum *= k
fact[k] = accum
#print 'fact_time', time() - start
data = sys.stdin.readlines()
num_tests = int(data.pop(0))
for ignore in xrange(0, num_tests):
n_and_steps = data.pop(0)
n, steps = map(lambda x: int(x), n_and_steps.split())
starting_point = map(lambda x: int(x), data.pop(0).split())
dimensions = map(lambda x: int(x), data.pop(0).split())
mem = {}
for di in xrange(n):
mem[di] = {}
for i in xrange(steps + 1):
mem[di][i] = {}
ways(di, starting_point[di], i)
start = time()
#print 'mem vector is done'
mem_set = {}
for i in xrange(n + 1):
for j in xrange(n + 1):
mem_set[(i, j)] = {}
answer = set_ways(0, n, steps)
#print answer
print answer % 1000000007
#print time() - start
mem[]
사전 을 채워 사용 가능한 모든 시스템 메모리를 소진 함을 의미합니다 . 내 답변을 정리해 주셔서 감사합니다. LaTeX에 익숙하지 않지만 다음에 노력할 것입니다.