Si nous avons n étapes et que nous pouvons monter 1 ou 2 étapes à la fois, il existe une relation de Fibonacci entre le nombre d’étapes et les moyens de les gravir. IF et SEULEMENT si nous ne comptons pas 2 + 1 et 1 + 2 comme différents.
Cependant, ce n'est plus le cas, en plus de devoir ajouter une troisième option en 3 étapes. Comment puis-je faire cela?
Ce que j'ai:
1 step = 1 way
2 steps = 2 ways: 1+1, 2
3 steps = 4 ways: 1+1+1, 2+1, 1+2, 3
Je ne sais pas où aller à partir d'ici pour connaître le nombre de voies pour n escaliers
Je reçois 7 pour n = 4 et 14 pour n = 5 j’obtiens 14 + 7 + 4 + 2 + 1 en faisant la somme de toutes les combinaisons qui le précèdent. donc manières pour n étapes = n-1 voies + n-2 voies + .... 1 voies en supposant que j'ai gardé toutes les valeurs. Programmation DYNAMIQUE . 1 2 et 3 étapes constitueraient le scénario de base, est-ce exact?
Je dirais que la formule se présentera de la manière suivante:
K(1) = 1
K(2) = 2
k(3) = 4
K(n) = K(n-3) + K(n-2) + K(n - 1)
La formule dit que pour atteindre la nième étape, nous devons d’abord atteindre:
K (4) = 7, K(5) = 13 etc.
Vous pouvez utiliser la formule récursive ou utiliser la programmation dynamique.
# recursion requirement: it returns the number of way up
# a staircase of n steps, given that the number of steps
# can be 1, 2, 3
def how_many_ways(n)
# this is a bit Zen like, if 0 steps, then there is 1 way
# and we don't even need to specify f(1), because f(1) = summing them up
# and so f(1) = f(0) = 1
# Similarly, f(2) is summing them up = f(1) + f(0) = 1 + 1 = 2
# and so we have all base cases covered
return 1 if n == 0
how_many_ways_total = 0
(1..3).each do |n_steps|
if n >= n_steps
how_many_ways_total += how_many_ways(n - n_steps)
end
end
return how_many_ways_total
end
0.upto(20) {|n| puts "how_many_ways(#{n}) => #{how_many_ways(n)}"}
def how_many_ways(n)
# this is a bit Zen like, if 0 steps, then there is 1 way
# if n is negative, there is no way and therefore returns 0
return 1 if n == 0
return 0 if n < 0
return how_many_ways(n - 1) + how_many_ways(n - 2) + how_many_ways(n - 3)
end
0.upto(20) {|n| puts "how_many_ways(#{n}) => #{how_many_ways(n)}"}
#
# from 0 to 27: recursive: 4.72 second
# iterative: 0.03 second
#
def how_many_ways(n)
arr = [0, 0, 1]
n.times do
new_sum = arr.inject(:+) # sum them up
arr.Push(new_sum).shift()
end
return arr[-1]
end
0.upto(27) {|n| puts "how_many_ways(#{n}) => #{how_many_ways(n)}"}
how_many_ways(0) => 1
how_many_ways(1) => 1
how_many_ways(2) => 2
how_many_ways(3) => 4
how_many_ways(4) => 7
how_many_ways(5) => 13
how_many_ways(6) => 24
how_many_ways(7) => 44
how_many_ways(8) => 81
how_many_ways(9) => 149
how_many_ways(10) => 274
how_many_ways(11) => 504
how_many_ways(12) => 927
how_many_ways(13) => 1705
.
.
how_many_ways(22) => 410744
how_many_ways(23) => 755476
how_many_ways(24) => 1389537
how_many_ways(25) => 2555757
how_many_ways(26) => 4700770
how_many_ways(27) => 8646064
J'aime l'explication de @ MichałKomorowski et le commentaire de @rici. Je pense que si cela dépend de la connaissance de K(3) = 4
, il faut alors compter manuellement.
Obtenez facilement l'intuition du problème:
Pensez que vous montez des escaliers et que les mesures que vous pouvez prendre sont 1 & 2
Le total non. des moyens d'atteindre l'étape 4 = total non. des moyens d'atteindre l'étape 3 + Nombre total de moyens d'atteindre l'étape 2
Comment?
Fondamentalement, il n’ya que deux étapes possibles à partir desquelles vous pouvez atteindre l’étape 4.
Ce sont les seules possibilités par lesquelles vous pouvez atteindre l'étape 4
De même, il n'y a que deux façons possibles d'atteindre l'étape 2
F(n) = F(n-1) + F(n-2)
F (0) = 0 et F(1) = 1 sont les cas de base. À partir de là, vous pouvez commencer à construire F (2), F(3), etc. Ceci est similaire à la série Fibonacci.
Si le nombre d’étapes possibles est augmenté, disons [1,2,3]. Désormais, vous disposez d’une option supplémentaire pour chaque étape, c’est-à-dire que vous pouvez sauter directement de trois étapes précédentes.
La formule deviendrait alors
F(n) = F(n-1) + F(n-2) + F(n-3)
Regardez cette vidéo pour comprendre Problème d'escalier Série Fibonacci
Compréhension facile du code: problème d'escalier geeksforgeeks
def count(steps):
sol = []
sol.append(1)
sol.append(1 + sol[0])
sol.append(1 + sol[1] + sol[0])
if(steps > 3):
for x in range(4, steps+1):
sol[(x-1)%3] = sum(sol)
return sol[(steps-1)%3]
Compter les moyens d'atteindre le nth escalier utilisant les étapes 1, 2, 3.
Nous pouvons compter en utilisant des méthodes récursives simples.
// Header File
#include<stdio.h>
// Function prototype for recursive Approch
int findStep(int);
int main(){
int n;
int ways=0;
ways = findStep(4);
printf("%d\n", ways);
return 0;
}
// Function Definition
int findStep(int n){
int t1, t2, t3;
if(n==1 || n==0){
return 1;
}else if(n==2){
return 2;
}
else{
t3 = findStep(n-3);
t2 = findStep(n-2);
t1 = findStep(n-1);
return t1+t2+t3;
}
}
Ma solution est en Java ... J'ai décidé de résoudre ce problème de bas en haut.
Je commence par avoir un tableau vide de chemins actuels [] À chaque étape, j'ajouterai toutes les tailles de pas possibles {1,2,3}
Première étape [] -> [[1], [2], [3]]
Deuxième étape [[1], [2], [3]] -> [[1,1], [1,2], [1,3], [2,1], [2,2 ], [2,3], [3,1] [3,2], [3,3]]
Itération 0: []
Itération 1: [[1], [2], [3]]
Itération 2: [[1,1], [1,2], [1,3], [2,1], [2,2], [2,3], [3,1], [3,2 ], [3,3]]
Itération 3 [[1,1,1], [1,1,2], [1,1,3] ....]
Les longueurs de séquence sont les suivantes: .1. 1 2 3 5 8 13 21
Ma fonction step s'appelle build
public class App {
public static boolean isClimedTooHigh(List<Integer> path, int maxSteps){
int sum = 0;
for (Integer i : path){
sum+=i;
}
return sum>=maxSteps;
}
public static void modify(Integer x){
x++;
return;
}
/// 1 2 3
/// 11 12 13
/// 21 22 23
/// 31 32 33
///111 121
public static boolean build(List<List<Integer>> paths, List<Integer> steps, int maxSteps){
List<List<Integer>> next = new ArrayList<List<Integer>>();
for (List<Integer> path : paths){
if (isClimedTooHigh(path, maxSteps)){
next.add(path);
}
for (Integer step : steps){
List<Integer> p = new ArrayList<Integer>(path);
p.add(step);
next.add(p);
}
}
paths.clear();
boolean completed = true;
for (List<Integer> n : next){
if (completed && !isClimedTooHigh(n, maxSteps))
completed = false;
paths.add(n);
}
return completed;
}
public static boolean isPathEqualToMax(List<Integer> path, int maxSteps){
int sum = 0;
for (Integer i : path){
sum+=i;
}
return sum==maxSteps;
}
public static void calculate( int stepSize, int maxSteps ){
List<List<Integer>> paths = new ArrayList<List<Integer>>();
List<Integer> steps = new ArrayList<Integer>();
for (int i =1; i < stepSize; i++){
List<Integer> s = new ArrayList<Integer>(1);
s.add(i);
steps.add(i);
paths.add(s);
}
while (!build(paths,steps,maxSteps));
List<List<Integer>> finalPaths = new ArrayList<List<Integer>>();
for (List<Integer> p : paths){
if (isPathEqualToMax(p, maxSteps)){
finalPaths.add(p);
}
}
System.out.println(finalPaths.size());
}
public static void main(String[] args){
calculate(3,1);
calculate(3,2);
calculate(3,3);
calculate(3,4);
calculate(3,5);
calculate(3,6);
calculate(3,7);
return;
}
}
Vous trouverez ci-dessous plusieurs façons d’utiliser les étapes 1, 2 et 3.
1: 1
2: 11 2
3: 111 12 21 3
4: 1111 121 211 112 22 13 31
5: 11111 1112 1121 1211 2111 122 212 221 113 131 311 23 32
6: 111111 11112 11121 11211 12111 21111 1113 1131 1311 3111 123 132 312 321 213 231 33 222 1122 1221 2211 1212 2121 2112
Donc, selon la combinaison ci-dessus, le soln devrait être:
K(n) = K(n-3) + K(n-2) + K(n - 1)
k(6) = 24 which is k(5)+k(4)+k(3) = 13+7+4
Solution C++ basée sur la mémorisation récursive: Vous demandez à un escalier combien de manières nous pouvons atteindre? Si ce n'est pas l'escalier le plus haut, sa va demander à tous ses voisins et le résumer et vous rendre le résultat. Si c'est l'escalier le plus haut sa va dire 1.
vector<int> getAllStairsFromHere(vector<int>& numSteps, int& numStairs, int currentStair)
{
vector<int> res;
for(auto it : numSteps)
if(it + currentStair <= numStairs)
res.Push_back(it + currentStair);
return res;
}
int numWaysToClimbUtil(vector<int>& numSteps, int& numStairs, int currentStair, map<int,int>& memT)
{
auto it = memT.find(currentStair);
if(it != memT.end())
return it->second;
if(currentStair >= numStairs)
return 1;
int numWaysToClimb = 0;
auto choices = getAllStairsFromHere(numSteps, numStairs, currentStair);
for(auto it : choices)
numWaysToClimb += numWaysToClimbUtil(numSteps, numStairs, it, memT);
memT.insert(make_pair(currentStair, numWaysToClimb));
return memT[currentStair];
}
int numWaysToClimb(vector<int>numSteps, int numStairs)
{
map<int,int> memT;
int currentStair = 0;
return numWaysToClimbUtil(numSteps, numStairs, currentStair, memT);
}
Comptez le nombre total de façons de parcourir la distance avec 1, 2 et 3 étapes.
La complexité temporelle de la solution de récursivité est exponentielle, c'est-à-dire O (3n).
Puisque les mêmes problèmes de sous sont résolus à nouveau, ce problème a une propriété de sous-problèmes qui se chevauchent. Donc, le problème de somme carrée a les propriétés d’un problème de programmation dynamique.
public class MaxStepsCount {
/** Dynamic Programming. */
private static int getMaxWaysDP(int distance) {
int[] count = new int[distance+1];
count[0] = 1;
count[1] = 1;
count[2] = 2;
/** Memorize the Sub-problem in bottom up manner*/
for (int i=3; i<=distance; i++) {
count[i] = count[i-1] + count[i-2] + count[i-3];
}
return count[distance];
}
/** Recursion Approach. */
private static int getMaxWaysRecur(int distance) {
if(distance<0) {
return 0;
} else if(distance==0) {
return 1;
}
return getMaxWaysRecur(distance-1)+getMaxWaysRecur(distance-2)
+getMaxWaysRecur(distance-3);
}
public static void main(String[] args) {
// Steps pf 1, 2 and 3.
int distance = 10;
/** Recursion Approach. */
int ways = getMaxWaysRecur(distance);
System.out.println(ways);
/** Dynamic Programming. */
ways = getMaxWaysDP(distance);
System.out.println(ways);
}
}
Mon article sur ce blog:
http://javaexplorer03.blogspot.in/2016/10/count-number-of-ways-to-cover-distance.html
Implémentation récursive Java basée sur Réponse de Michał :
public class Tribonacci {
// k(0) = 1
// k(1) = 1
// k(2) = 2
// k(3) = 4
// ...
// k(n) = k(n-3) + k(n-2) + k(n - 1)
static int get(int n) {
if (n == 0) {
return 1;
} if (n == 1) {
return 1;
} else if (n == 2) {
return 2;
//} else if (n == 3) {
// return 4;
} else {
return get(n - 3) + get(n - 2) + get(n - 1);
}
}
public static void main(String[] args) {
System.out.println("Tribonacci sequence");
System.out.println(Tribonacci.get(1));
System.out.println(Tribonacci.get(2));
System.out.println(Tribonacci.get(3));
System.out.println(Tribonacci.get(4));
System.out.println(Tribonacci.get(5));
System.out.println(Tribonacci.get(6));
}
}
Voici un O(Nk) Implémentation Java utilisant la programmation dynamique:
public class Sample {
public static void main(String[] args) {
System.out.println(combos(new int[]{4,3,2,1}, 100));
}
public static int combos(int[] steps, int stairs) {
int[][] table = new int[stairs+1][steps.length];
for (int i = 0; i < steps.length; i++) {
for (int n = 1; n <= stairs; n++ ) {
int count = 0;
if (n % steps[i] == 0){
if (i == 0)
count++;
else {
if (n <= steps[i])
count++;
}
}
if (i > 0 && n > steps[i]) {
count += table[n - steps[i]][i];
}
if (i > 0)
count += table[n][i-1];
table[n][i] = count;
}
}
for (int n = 1; n < stairs; n++) {
System.out.print(n + "\t");
for (int i = 0; i < steps.length; i++) {
System.out.print(table[n][i] + "\t");
}
System.out.println();
}
return table[stairs][steps.length-1];
}
}
L'idée est de remplir le tableau suivant 1 colonne à la fois de gauche à droite:
N (4) (4,3) (4,3,2) (4,3,2,1)
1 0 0 0 1
2 0 0 1 2
3 0 1 1 3
4 1 1 2 5
5 0 0 1 6
6 0 1 3 9
7 0 1 2 11
8 1 1 4 15
9 0 1 3 18
10 0 1 5 23
11 0 1 4 27
12 1 2 7 34
13 0 1 5 39
..
..
99 0 9 217 7803
100 8037