n солдат построены в одну шеренгу. Сколькими способами
можно выбрать из них несколько человек (хотя бы одного) так, чтобы среди вышедших
не было стоящих рядом?
Вход. Одно число n (1 ≤ n ≤ 90).
Выход. Выведите искомое количество способов.
Пример
входа |
Пример
выхода |
3 |
4 |
рекуррентное
соотношение
Обозначим через
f(n) количество искомых способов. Отметим,
что в f(n) входят только те способы,
в которых ходя бы один солдат выходит из строя.
Очевидно, что
f(1) = 1 (выходит один солдат) и f(2) = 2 (выходит или первый, или второй
солдат).
Пусть солдаты в
строю пронумерованы в убывающем порядке от n
до 1. Тогда выход из строя можно организовать одним из следующих трех способов:
·
выходит n-ый, а
все остаются на месте;
·
выходит n-ый,
тогда (n – 1)-ый должен остаться на
месте. После чего рекурсивно рассматривается решение для (n – 2) солдат;
·
n-ый остается на
месте. Тогда рекурсивно решаем задачу для (n
– 1) солдата;
Таким образом
получили рекуррентное соотношение:
Пример
При n = 4 имеется 7 возможных способов.
Значения функции f(i)
будем запоминать в ячейках f[i].
#define MAX 91
long long
res[MAX];
Вычислим значения f(i) (0 ≤ i ≤ MAX) по приведенной в анализе алгоритма формуле.
res[1] = 1;
res[2] = 2;
for(i = 3; i < MAX; i++)
res[i] = res[i-1] + res[i-2] + 1;
Прочитаем входное значение n и выведем результат.
scanf("%d",&n);
printf("%lld\n", res[n]);
#include <stdio.h>
#include <string.h>
#define MAX 91
long long m[MAX];
int i, n;
long long f(int n)
{
if (n == 1) return 1;
if (n == 2) return 2;
if (m[n] !=
-1) return m[n];
return m[n] =
f(n-1) + f(n-2) + 1;
}
int main(void)
{
scanf("%d",&n);
memset(m,-1,sizeof(m));
printf("%lld\n",f(n));
return 0;
}
Java реализация
import java.util.*;
public class Main
{
public static void
main(String[] args)
{
long res[] = new long[91];
res[1] =
1; res[2] = 2;
for(int i = 3;
i < 91; i++)
res[i] = res[i-1] +
res[i-2] + 1;
Scanner con = new
Scanner(System.in);
int n = con.nextInt();
System.out.println(res[n]);
con.close();
}
}
Java реализация
с запоминанием
import java.util.*;
public class Main
{
static int MAX = 91;
static long m[] = new long[MAX];
static long f(int n)
{
if (n ==
1) return 1;
if (n ==
2) return 2;
if (m[n] !=
-1) return m[n];
return m[n] = f(n-1) +
f(n-2) + 1;
}
public static void
main(String[] args)
{
Arrays.fill(m,
-1);
Scanner con = new
Scanner(System.in);
int n = con.nextInt();
System.out.println(f(n));
con.close();
}
}