
- •1.1 Арифметические операторы.
- •1.3. Логические операторы
- •1.6. Выражения
- •1.7. Преобразование типов
- •2.6. Вложение else if
- •2.7. Инструкция switch
- •3.1. Оператор цикл for
- •3.4. Цикл do-while
- •3.3. Цикл while
- •4.1. Алгоритм Евклида
- •4.2. Алгоритмы обмена чисел
- •4.3.А. Для заданного натурального числа определить количество единичных бит в его представлении.
- •4.3.B. Найти количество повторений каждой цифры у заданного натурального числа
- •4.3.C. Перевод из 10-й с/с в 2..9
- •5.1. Объявление и определение функций .
- •5.2. Функция main()
- •5.3. Функция main() с параметрами
- •5.4. Обмен данными между функциями. Возвращаемое значение
- •5.5. Параметры функции
- •5.6.A. Функция перевода числа в различные нумерации
- •5.6.C. Поиск количества единичных бит в двоичном представлении числа.
- •5.6.E. Вычисление n!
- •5.6.F. Вычисление сочетаний из n по m без факториала
- •7. Функции форматированного вывода
- •7. Функции форматированного вывода (продолжение)
- •8. Функции форматированного ввода
- •9. Функции общего назначения
- •Void srand(unsigned int );
- •11.1. Объявление и инициализация массива
- •11.3. Ввод-вывод массивов
- •11.4 Операции над элементами массива
- •11.5. Передача массивов функциям
- •11.6. Обработка одномерных и двумерных массивов
- •11.7. Поиск элемента с заданными характиристиками
- •12.1. Переменные-указатели
- •12.2. Oператоры для работы с указателями.
- •12.3. Арифметические действия с указателями.
- •12.4. Динамическое распределение памяти
- •12.5. Указатели и массивы
- •12.6. Массивы-параметры
- •12.7. Указатели на константы и константные указатели.
- •12.8. Указатели на функции.
- •12.9. Алгоритмы преобразование и перестановки .
- •12.10. Алгоритмы расширение и сжатие массивов
- •13.1Сортировка пузырьком
- •13.2Сортировка Вставками
- •13.3Сортировка выбором
- •13.4Линейный поиск
- •Int sprintf(char *buffer, const char *format, ...);
- •15 Цели введения новых типов:
- •Int fclose(file* stream);
- •Int feof(file* stream);
- •18. Функции и разработка программ
- •18.1. Функции с переменным количеством параметров
- •18.2. Глобальные и локальные переменные, область видимости и время существования.
- •18.3. Спецификаторы классов памяти.
- •18.4. Компоновка нескольких файлов в одну программу
- •18.5. Директивы препроцессора
- •Задача Иосифа Флавия
- •Задача о рюкзаке
- •Классическая архитектура компьютера
- •Процессор - программно-управляемое устройство
- •Регистры, назначение и характеристика
- •Xchg приемник, источник
- •23Команды сравнения:
- •25 Команды организации циклов:
- •26 Команды пересылки:
- •27 Логические команды:
- •28 Команды обработки строк
- •Префиксы повторения
- •29.1. Регистры сопроцессора
- •29.2. Команды пересылки данных
- •29.3. Арифметические команды
- •29.4. Команды сравнения чисел
- •29.5. Трансцендентные команды
- •29.6. Управляющие команды
- •30.1. Команда call
- •23.6. Внешние подпрограммы
- •23.7.Компилятор masm
Задача Иосифа Флавия
Пусть по кругу стоят n человек, начинают считать с 1-го, и каждый k-ый выбывает. Кто останется водить? Итак, получается такая рекуррентная зависимость:
к=2: J(n) = 1, J(n) = 2J(n/2) - 1, если n четное, J(n) = 2J((n - 1)/2) + 1, если n нечетное.
Пример решения задачи с циклично связным списком:
struct people{int number; people *next;};
void Step(people *&top, int k)
{
k--;
for (k; k>1; top=top->next, k--);
people *temp=top->next;
top->next=top->next->next;
top=top->next;
delete temp;
}
//Продолжение Иосифа Флавия
void main()
{
setlocale(LC_ALL,".1251"); int n, k;
cout<<"Введите количество людей в группе?\n";
cin>>n;
cout<<"Какого по счету удаляем?\n";
cin>>k;
if (k==1)
{
cout<<"В живых останется человек с номером "<<n<<endl; return;
}
people *top=new people;
top->number=1;
people *last=top;
for (int i=2; i<=n; i++)
{
people *p=new people;
p->number=i;
last->next=p;
last=p;
}
last->next=top;
for (int i=1; i<n; i++)
Step(top, k);
cout<<"В живых останется человек с номером "<<top->number<<endl;
delete top;
}
Задача о рюкзаке
Имеются m предметов с номерами от 0 до m-1, для каждого из которых известна масса в килограммах pj и стоимость cj (j = 0,1,…,m-1). Определить, какие предметы необходимо положить в рюкзак, чтобы их общая масса не превышала P кг, а общая стоимость была максимальной. Сколько предметов каждого типа он должен положить в рюкзак, чтобы суммарная ценность снаряжения была максимальной при ограничении на массу рюкзака?
Жадный алгоритм для задачи о рюкзаке состоит в следующем: Выбрать максимально дорогой предмет, стоимости Cmax . Упорядочить предметы по «удельной стоимости» (стоимости деленной на вес), и набивать рюкзак наиболее «удельно дорогими» предметами, пока они влезают. Пусть стоимость этого решения Cgreedy В зависимости от того, что больше, Cmax или Cgreedy, выбрать первое или второе решение.Задача укладки рюкзака сложна. Если перебирать всевозможные подмножества данного набора из k предметов, то получится решение сложности не менее чем O(2k). Мы рассмотрим решение данной задачи для случая, когда все входные данные - целочисленные, сложность которого будет O(kW). Рассмотрим следующую функцию. Пусть R(s, n) есть максимальная стоимость предметов, которые можно уложить в рюкзак максимальной вместимости n, если можно использовать только первые s предметов из заданных k. Зададим краевые значения функции R(s, n). Если s = 0, то R(0, n) = 0 для всех n (ни один предмет нельзя брать, поэтому максимальная стоимость равна 0). Если n = 0, то R(s, 0) = 0 для всех s (можно брать любые из первых s предметов, но вместимость рюкзака равна 0).
// О рюкзаке
Cоставим рекуррентное соотношение: необходимо из предметов с номерами 1, ..., s составить рюкзак максимальной стоимости, чей вес не превышает n. При этом возможно два случая: когда в максимальный рюкзак включен предмет с номером s и когда предмет s не попал в максимальный рюкзак. Если предмет s не попал в максимальный рюкзак массы n, то максимальный рюкзак будет составлен только из предметов с номерами 1, ..., s - 1, следовательно, A(s, n) = A(s - 1, n). Если же в максимальный рюкзак включен предмет s, то масса оставшихся предметов не превышает n - ws, а от добавления предмета s общая стоимость рюкзака увеличивается на ps. Значит, A(s, n) = A(s - 1, n - ws) + ps. Теперь из двух возможных вариантов составить рюкзак массы <= n, из предметов 1, ..., s нужно выбрать :
A(s, n) = max (A(s - 1, n), A(s - 1, n - ws) + ps.
Ханойские башни
Есть три стержня A, B, и C. На стержень A надето N дисков, наверху самый маленький, каждый следующий диск больше предыдущего, а внизу самый большой. На другие стержни дисков не надето. Hеобходимо перенести диски со стержня A на стержень C, пользуясь стержнем B, как вспомогательным, так, чтобы диски на стержне C располагались в том же порядке, в каком они располагаются на диске A перед перемещением. При перемещении никогда нельзя класть больший диск на меньший.
void Move(int n, char x,y,z); //х - А y - В z - C { if (n==1) scanf(“ диск 1 %d -> %d“ ,x,y); else if (n>1) { Move(n-1,x,z,y); printf(“диск %2d %d ->%d”,n,x,y); Move(n-1,z,y,x); }
Метод быстрой сортировки Хоара
Метод быстрой сортировки массива разрботан в 1962 году профессором Оксфордского университета К. Хоаром. Алгоритм состоит в том, чтобы, выбрав некоторый элемент разделяющим, переместить все элементы меньшие (или равные) его левее, а большие – правее. После этого применить тот же ход для левой части и правой части массива, если в этой части больше одного элемента. Алгоритм – рекурсивный, т.е. соответствующая процедура обращается при реализации к самой себе. Сложность алгоритма – O(n*logn) – в среднем. В худшем случае (когда после разделения на каждом шаге один из подмассивов состоит из одного элемента, а второй – из оставшихся) сложность O(n2)
void qsort(int a[], int l, int r) { int i = l, j = r, p; int x = a[(l + r)/2]; while (i <= j) {
while (a[i] < x) ++i; while (x < a[j])
--j;
if (i <= j) { p = a[i]; a[i] = a[j]; a[j] = p; i++; j--; }
} if (l < j) qsort(a, l, j); if (i < r) qsort(a, i, r);
}
Рекурсивные функции сортировки
Упорядочить элементы последовательности A=(ai), i=1..n, используя рекурсивную функцию сортировки. void rec_sort(int *a, int i, int n) // рекурсивной функция сортировки вставками { if (i < n) { int max_el = a[i], max_ind = i; for (int j = i; j < n; ++j) if (a[j] > max_el) { max_el = a[j]; max_ind = j;}
if (max_ind > i) { a[i] ^= a[max_ind]; a[max_ind] ^= a[i]; a[i] ^= a[max_ind];} rec_sort(a, i+1, n); }}
Решение комбинаторных задач: генерация k-элементных подмножеств, генерация перестановок
Генерация k-элементных подмножеств В комбинаторике такие подмножества называют сочетаниями из n элементов по k элементов и обозначают Cnk , при программировании гораздо удобнее использовать следующие рекуррентные соотношения
Обычно генерацию всех k-элементных подмножеств проводят в лексикографическом порядке, тем более что в данном случае это не приводит ни к усложнению алгоритма, ни к увеличению его вычислительной трудоемкости. Порядок подмножеств называется лексикографическим, если для любых двух подмножеств справедливо, что ранее должно быть сгенерировано то из них, из индексов элементов которого можно составить меньшее k-значное число в n-ричной системе счисления (или в десятичной, для n < 10). Идея сведения данной задачи к задаче меньшей размерности следующая. Первым элементом подмножества может быть любой элемент, начиная с первого и заканчивая (n – k + 1)-м элементом. После того, как индекс первого элемента подмножества зафиксирован, осталось выбрать k – 1 элемент из элементов с индексами, большими, чем у первого. Далее поступаем аналогично. Когда выбран последний элемент, то мы достигли конечного уровня рекурсии и выбранное подмножество можно обработать.