Для сложных задач я предлагаю выполнить задачу для небольших задач и посмотреть, какие закономерности вы найдете. Например, в «Ханойских башнях» начните с задачи размером один, затем два, затем три и т. д. В какой-то момент вы, вероятно, начнете видеть закономерность и поймете, что некоторые из ваших проблем делать то же самое, что вы должны были делать с задачами меньшего размера, или что это достаточно похоже, чтобы вы могли использовать ту же технику, что и раньше, но с некоторыми вариациями.
Я только что сам разобрался с проблемой Ханойских башен и изучил собственное мышление. Я начал с проблемы размера один:
We have one disk on peg A.
*** Move it to peg C.
Done!
Теперь на двоих.
We have two disks on peg A.
I need to use peg B to get the first disk out of the way.
*** Move from peg A to peg B
Now I can do the rest
*** Move from peg A to peg C
*** Move from peg B to peg C
Done!
Теперь на троих.
Все начинает становиться немного интереснее. Решение не столь очевидно. Однако я понял, как переместить два диска с одного стержня на другой, поэтому, если бы я мог переместить два диска с стержня A на стержень B, затем переместить один диск с стержня A на стержень C, а затем два диска с стержня B. чтобы привязать C, я был бы сделан! Моя логика для случая с двумя дисками сработает, разве что штифты разные. Если мы поместим логику в функцию и создадим параметры для привязок, то сможем повторно использовать логику.
def move2(from_peg,to_peg,other_peg):
# We have two disks on from_peg
# We need to use other_peg to get the first disk out of the way
print 'Move from peg '+from_peg+' to peg '+other_peg
# Now I can do the rest
print 'Move from peg '+from_peg+' to peg '+to_peg
print 'Move from peg '+other_peg+' to peg '+to_peg
Тогда логика такая:
move2('A','B','C')
print 'Move from peg A to peg C'
move2('B','C','A')
Я могу сделать это проще, используя функцию move1:
def move1(from_peg,to_peg):
print 'Move from '+from_peg+' to '+to_peg
Теперь моя функция move2 может быть
def move2(from_peg,to_peg,other_peg):
# We have two disks on from_peg
# We need to use other_peg to get the first disk out of the way
move1(from_peg,other_peg,to_peg)
# Now I can do the rest
move1(from_peg,to_peg)
move1(other_peg,to_peg)
Хорошо, а четыре?
Похоже, я могу применить ту же логику. Мне нужно получить три диска от привязки A к привязке B, затем один от A к C, затем три от B к C. Я уже решил переместить три, но с неправильными привязками, поэтому я обобщу это:
def move3(from_peg,to_peg,other_peg):
move2(from_peg,other_peg,to_peg)
move1(from_peg,to_peg)
move2(other_peg,to_peg,from_peg)
Прохладный! И подождите, ход 3 и ход 2 теперь очень похожи, и в этом есть смысл. Для задачи любого размера мы можем переместить все диски, кроме одного, на привязку B, затем переместить один диск из A в C, затем переместить все диски с привязки B на привязку C. Таким образом, наша функция перемещения может просто взять количество дисков как параметр:
def move(n,from_peg,to_peg,other_peg):
move(n-1,from_peg,other_peg,to_peg)
move1(from_peg,to_peg)
move(n-1,other_peg,to_peg,from_peg)
Это выглядит очень похоже, но не работает в случае, когда n==1, потому что в итоге мы вызываем move(0,...). Итак, нам нужно справиться с этим:
def move(n,from_peg,to_peg,other_peg):
if n==1:
move1(from_peg,to_peg)
else:
move(n-1,from_peg,other_peg,to_peg)
move1(from_peg,to_peg)
move(n-1,other_peg,to_peg,from_peg)
Превосходно! Как насчет задачи размером пять? Мы просто вызываем move(5,'A','C','B'). Похоже, что любой размер задачи — это одно и то же, поэтому наша основная функция такова:
def towers(n):
move(n,'A','C','B')
и мы закончили!
person
Vaughn Cato
schedule
28.03.2014
10! = 1 * 10! = 10 * 9!
, поэтому и проблема, и решение имеют формуa * b!
. Большинство людей находят абстракции трудными. Но на самом деле все дело в попытках найти сходство в разных ситуациях. Вы даже можете практиковать это в своей повседневной жизни (попытайтесь увидеть сходство двух разных концепций). - person Vincent van der Weele   schedule 28.03.2014