Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
АМ_5_LR_6.doc
Скачиваний:
6
Добавлен:
23.08.2019
Размер:
131.07 Кб
Скачать

Приклад виконання роботи

Приклад 1. Завдання про розрізування прямокутника на квадрати.

Дано прямокутник, сторони якого виражені натуральними числами. Розріжте його на мінімальне число квадратів з натуральними сторонами. Знайдіть число квадратів, що вийшли.

Розробимо рекурсивну тріаду.

Параметризація: m, n - натуральні числа, що відповідають розмірам прямокутника.

База рекурсії: для m=n число квадратів, що вийшли, дорівнює 1, тому що даний прямокутник уже є квадратом.

Декомпозиція: якщо m≠n, те можливі два випадки m < n або m > n. Відрізаємо від прямокутника найбільший по площі квадрат з натуральними сторонами. Довжина сторони такого квадрата дорівнює найменшої зі сторін прямокутника. Після того, як квадрат буде відрізаний, розміри прямокутника стануть наступні: більша сторона зменшиться на довжину сторони квадрата, а менша не зміниться. Число шуканих квадратів буде обчислюватися як число квадратів, на які буде розрізаний отриманий прямокутник, плюс один (відрізаний квадрат). До прямокутника, що вийшов, застосуємо аналогічні міркування: перевіримо на відповідність базі або перейдемо до декомпозиції (рис. 2).

Рисунок 2.  Приклад розрізування прямокутника 135 на квадрати

#include "stdafx.h"

#include <iostream>

using namespace std;

int kv(int m,int n);

int _tmain(int argc, _TCHAR* argv[]) {

int a,b,k;

printf("Введіть сторони прямокутника ->");

scanf("%d%d",&a,&b);

k = kv(a,b);

printf("Прямокутник зі сторонами %d и %d можна розрізати

на %d квадратів",a,b,k);

system("pause");

return 0;

}

int kv(int m,int n){ //m,n – сторони прямокутника

if(m==n) return 1; //база рекурсії

if(m>n) return 1+kv(m-n,n); //декомпозиція для m>n

return 1+kv(m,n-m); //декомпозиція для m<n

}

Характеристиками розглянутого методу оцінки алгоритму будуть наступні величини (рис. 34.3).

D = (13, 5)

D = (m, n), m n, гірший випадок

R(D)=6

R(D)=m

RV(D)=4

RV(D)=m-2

RL(D)=1

RL(D)=1

HR(D)=6

HR(D)=m

Рисунок 3.  Приклад повного дерева рекурсії для розрізування прямокутника 135 на квадрати

Приклад 2. Завдання про розбивку цілого на частині.

Знайдіть кількість розбивок натурального числа на суму натуральних доданків.

Розбивка має на увазі подання натурального числа у вигляді суми натуральних доданків, при цьому суми повинні відрізнятися набором чисел, а не їхньою послідовністю. У розбивку також може входити одне число.

Наприклад, розбивка числа 6 буде представлено 11 комбінаціями:

6

5+1

4+2, 4+1+1

3+3, 3+2+1, 3+1+1+1

2+2+2, 2+2+1+1, 2+1+1+1+1

1+1+1+1+1+1

Розглянемо рішення в загальному виді. Нехай залежність R(n,k) обчислює кількість розбивок числа n на суму що складають, не переважаючих k. Опишемо властивості R(n,k).

Якщо в сумі всі доданки не перевершують 1, то таке подання єдине, тобто R(n,k)=1.

Якщо розглянуте число дорівнює 1, то при будь-якім натуральному значенні другого параметра розбивка також єдина: R(n,k)=1.

Якщо другий параметр перевершує значення першого , то має місце рівність R(n,k)=R(n,n), тому що для подання натурального числа в суму не можуть входити числа, що перевершують його.

Якщо в суму входить доданок, рівне першому параметру, то таке подання також єдине (містить тільки цей доданок), тому має місце рівність:R(n,n)=R(n,n-1)+1.

Якщо в торбу входити доданок, рівне першому параметру, те таке подання також єдине (містить тільки цей доданок), тому має місце рівність: (n>k). Розіб'ємо всі подання числа n на непересічні розкладання: в одні обов'язково буде входити доданок k, а інші суми не містять k. Перша група сум, що містить k, еквівалентна залежності R(n-k,k), що треба після вирахування числа k з кожної суми. Друга група сум містить розбивку числа n на доданки, кожне з яких не перевершує k-1, тобто число таких подань дорівнює R(n,k-1). Тому що обидві групи сум не перетинаються, то R(n,k)=R(n-k,k)+R(n,k-1).

Розробимо рекурсивну тріаду.

Параметризація: Розглянемо розбивку натурального числа n на суму таких що складають, які не перевершують натурального числа k.

База рекурсії: виходячи із властивостей розглянутої залежності, виділяються два базових випадки:

при n=1   R(n,k)=1,

при k=1   R(n,k)=1.

База рекурсії: виходячи із властивостей розглянутої залежності, виділяються два базових випадки:

при n=k   R(n,k)=R(n,n-1)+1,

при n<k   R(n,k)=R(n,n),

при n>k   R(n,k)=R(n-k,k)+R(n,k-1).

#include "stdafx.h"

#include <iostream>

using namespace std;

unsigned long int Razbienie(unsigned long int n,

unsigned long int k);

int _tmain(int argc, _TCHAR* argv[]){

unsigned long int number, max,num;

printf ("\nВведіть натуральне число: ");

scanf ("%d", &number);

printf ("Введіть максимальний натуральний додаток в

сумі: ");

scanf ("%d", &max);

num=Razbienie(number,max);

printf ("Число %d можна представити у вигляді суми з

максимальним доданком %d.", number, max);

printf ("\nКількість розбивок дорівнює %d",num);

system("pause");

return 0;

}

unsigned long int Razbienie(unsigned long int n,

unsigned long int k){

if(n==1 || k==1) return 1;

if(n<=k) return Razbienie(n,n-1)+1;

return Razbienie(n,k-1)+Razbienie(n-k,k);

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]