Строка, состоящая из букв
A, B и C, называется запрещенной, если в ней встречаются три подряд буквы, одна
из которых A, другая B, а третья C. Например, строка BAACAACCBAAA является
запрещенной, в то время как AABBCCAABB нет.
Вычислите количество незапрещенных
строк длины n.
Вход. Каждая строка содержит одно число n (1 ≤ n ≤
30).
Выход. Для каждого значения n
выведите в
отдельной строке количество незапрещенных строк длины n.
Пример
входа |
Пример
выхода |
2 3 4 |
9 21 51 |
РЕШЕНИЕ
рекурсия
Анализ алгоритма
Занесем в rep[i] количество незапрещенных строк длины i, у которых две последние буквы
одинаковы. В ячейке nonrep[i] будем
хранить число незапрещенных строк длины i,
у которых две последние буквы разные. Ответом на задачу будет значение rep[n] + nonrep[n].
Вычислим непосредственно
значения ячеек:
Вычисление rep[i]. На место i - ой буквы необходимо ставить ту же букву, которая стоит на (i – 1) - ом месте.
rep[i] = rep[i – 1] + nonrep[i – 1]
Вычисление nonrep[i]. Если (i – 1) - ая и (i –
2) - ая буквы одинаковы, то на i - ое место можно поставить любую из
двух букв, не совпадающую с ней. Если (i
– 1) - ая и (i – 2) - ая буквы разные, то (i – 1) - ую букву продублировать в качестве i - ой нельзя, нельзя поставить на i - ое место букву, отличную от (i – 1) - ой и (i –
2) - ой (три разные буквы подряд ставить
запрещено). Поэтому в этом случае на i
- ое место следует ставить (i – 2) -
ую букву.
nonrep[i] = 2 * rep[i – 1] +
nonrep[i – 1]
Например, ячейки массивов
rep и nonrep будут содержать следующие значения:
Если обозначить через rep(n) и nonrep(n) функции, вычисляющие количество незапрещенных строк длины n соответственно с повторяющимися двумя
последними буквами и не повторяющимися, то
можно записать рекуррентное соотношение:
,
Реализация алгоритма
Объявим глобальные переменные.
long long rep[31], nonrep[31];
Заполняем ячейки массивов rep и nonrep согласно выше приведенным
формулам.
long long countNotForbidden(int
n)
{
int i;
rep[1]
= 0; rep[2] = 3;
nonrep[1] = 3; nonrep[2] = 6;
for(i = 3; i <= n; i++)
{
rep[i] = rep[i-1] + nonrep[i-1];
nonrep[i] = 2 * rep[i-1] + nonrep[i-1];
}
return rep[n] + nonrep[n];
}
Основная часть программы.
while(scanf("%d",&n) == 1)
{
res =
countNotForbidden(n);
printf("%lld\n",res);
}
Реализация алгоритма – рекурсия с запоминанием
#include <stdio.h>
#include <string.h>
int n;
long long repMem[31], nonrepMem[31];
long long nonrep(int n);
long long rep(int n)
{
if (n == 1) return 0;
if (n == 2) return 3;
if (repMem[n] != -1) return
repMem[n];
return repMem[n] = rep(n - 1) + nonrep(n - 1);
}
long long nonrep(int n)
{
if (n == 1) return 3;
if (n == 2) return 6;
if (nonrepMem[n] != -1) return
nonrepMem[n];
return nonrepMem[n] = 2 * rep(n - 1) + nonrep(n - 1);
}
int main(void)
{
memset(repMem,-1,sizeof(repMem));
memset(nonrepMem,-1,sizeof(nonrepMem));
while(scanf("%d",&n)
== 1)
printf("%lld\n",rep(n) +
nonrep(n));
return 0;
}
Java реализация
import java.util.*;
public class
{
static int MAX = 31;
static long rep[] = new long[MAX], nonrep[] = new long[MAX];
static long countNotForbidden(int n)
{
rep[1] = 0; rep[2] = 3;
nonrep[1] = 3; nonrep[2] = 6;
for(int i = 3; i <= n; i++)
{
rep[i] = rep[i-1] + nonrep[i-1];
nonrep[i] = 2 * rep[i-1] + nonrep[i-1];
}
return rep[n] + nonrep[n];
}
public static void main(String[] args)
{
Scanner con = new Scanner(System.in);
while(con.hasNextInt())
{
int n = con.nextInt();
long res = countNotForbidden(n);
System.out.println(res);
}
}
}
Java реализация – рекурсия
с запоминанием
import java.util.*;
public class
{
static long repMem[] = new long[31];
static long nonrepMem[] = new long[31];
static long rep(int n)
{
if (n == 1) return 0;
if (n == 2) return 3;
if (repMem[n] != -1) return repMem[n];
return repMem[n] = rep(n - 1) + nonrep(n - 1);
}
static long nonrep(int n)
{
if (n == 1) return 3;
if (n == 2) return 6;
if (nonrepMem[n] != -1) return nonrepMem[n];
return nonrepMem[n] = 2 * rep(n - 1) + nonrep(n - 1);
}
public static void main(String[] args)
{
Scanner con = new Scanner(System.in);
Arrays.fill(repMem, -1);
Arrays.fill(nonrepMem, -1);
while(con.hasNext())
{
int n = con.nextInt();
System.out.println(rep(n) + nonrep(n));
}
con.close();
}
}