using System;
using System.Text;
namespace Dynamic.Algoriths
{
class Program
{
/// <summary>
/// На вершине лесенки, содержащей N ступенек, находится мячик, который начинает прыгать по ним вниз, к основанию.
/// Мячик может прыгнуть на следующую ступеньку, на ступеньку через одну или через 2. (То есть, если мячик лежит на 8-ой ступеньке, то он может переместиться на 5-ую, 6-ую или 7-ую.)
/// Определить число всевозможных «маршрутов» мячика с вершины на землю.
/// </summary>
/// <param name="n"></param>
static void BallJump(int n)
{
//На первую ступеньку можно попасть только одним образом — сделав прыжок с длиной равной единице.
//На вторую ступеньку можно попасть сделав прыжок длиной 2, или с первой ступеньки — всего 2 варианта.
//На третью ступеньку можно попасть сделав прыжок длиной три, с первой или со втрой ступенек.
//Т.е.всего 4 варианта(0->3; 0->1->3; 0->2->3; 0->1->2->3).
//Теперь рассмотрим четвёртую ступеньку. На неё можно попасть с первой ступеньки — по одному маршруту на каждый маршрут до неё, со второй или с третьей — аналогично.
//Иными словами, количество путей до 4 - й ступеньки есть сумма маршрутов до 1 - й, 2 - й и 3 - й ступенек.Математически выражаясь, F(N) = F(N - 1) + F(N - 2) + F(N - 3).
//Первые три ступеньки будем считать начальными состояниями.
int[] vars = new int[3];
vars[0] = 1; vars[1] = 2; vars[2] = 4;
for (int i = 3; i < n; i++)
{
vars[i % 3] = vars[0] + vars[1] + vars[2];
}
//Так как каждое следующее значение зависит только от трёх предыдущих, ни одно значение под индексом меньше i-3 нам бы не пригодилось.
//В приведённом выше коде мы записываем новое значение на место самого старого, не нужного больше.
//Цикличность остатка от деления на 3 помогает нам избежать кучи условных операторов.
//Просто, компактно, элегантно.
Console.WriteLine(vars[(n - 1) % 3]);
}
/// <summary>
/// В прямоугольной таблице NxM в начале игрок находится в левой верхней клетке.
/// За один ход ему разрешается перемещаться в соседнюю клетку либо вправо, либо вниз (влево и вверх перемещаться запрещено).
/// Посчитайте, сколько есть способов у игрока попасть в правую нижнюю клетку.
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
static int MatrixPath1(int i, int j)
{
if (i == 1 || j == 1) return 1;
return MatrixPath1(i - 1, j) + MatrixPath1(i, j - 1);
}
static int MatrixPath2(int Imax, int Jmax)
{
var dp = new int[Imax, Jmax];
for (int i = 0; i < Imax; i++)
{
for (int j = 0; j < Jmax; j++)
{
if (i == 0 || j == 0)
{
dp[i, j] = 1;
}
else
{
dp[i, j] = dp[i - 1, j] + dp[i, j - 1];
}
}
}
return dp[Imax - 1, Jmax - 1];
}
/// <summary>
/// Имеется калькулятор, который выполняет три операции:
/// Прибавить к числу X единицу;
/// Умножить число X на 2;
/// Умножить число X на 3.
/// Определите, какое наименьшее число операций необходимо для того, чтобы получить из числа 1 заданное число N.
/// Выведите это число, и, на следующей строке, набор исполненных операций вида «111231».
/// </summary>
/// <param name="n"></param>
static void Calculator(int N)
{
//Правильное решение заключается в нахождении для каждого числа от 2 до N минимального количества действий на основе предыдущих элементов,
//иначе говоря: F(N) = min(F(N-1), F(N/2), F(N/3)) + 1. Следует помнить, что все индексы должны быть целыми.
//Для воссоздания списка действий необходимо идти в обратном направлении и искать такой индекс i, что F(i)=F(N),
//где N — номер рассматриваемого элемента. Если i=N-1, записываем в начало строки 1, если i=N/2 — двойку, иначе — тройку.
int[] a = new int[N + 1];
a[1] = 0;
int min;
int i;
for (i = 2; i < N + 1; i++)
{
min = a[i - 1] + 1;
if (i % 2 == 0) min = Math.Min(min, a[i / 2] + 1);
if (i % 3 == 0) min = Math.Min(min, a[i / 3] + 1);
a[i] = min;
}
StringBuilder ret = new StringBuilder();
i = N;
while (i > 1)
{
if (a[i] == a[i - 1] + 1)
{
ret.Insert(0, 1);
i--;
continue;
}
if (i % 2 == 0 && a[i] == a[i / 2] + 1)
{
ret.Insert(0, 2);
i /= 2;
continue;
}
ret.Insert(0, 3);
i /= 3;
}
Console.WriteLine(a[N]);
Console.WriteLine(ret);
}
static void Main(string[] args)
{
BallJump(15);
Console.WriteLine(MatrixPath1(8, 5));
Console.WriteLine(MatrixPath2(8, 5));
Calculator(123);
Console.WriteLine("Hello World!");
}
}
}