Условная инструкция

Все ранее рассматриваемые программы имели линейную структуру: все инструкции выполнялись последовательно одна за одной, каждая записанная инструкция обязательно выполняется.

Допустим мы хотим по данному числу x определить его абсолютную величину (модуль). Для этого необходимо нарушить линейную логику программы. Программа должна напечатать значение переменной x, если x>0 или же величину -x в противном случае. Линейная структура программы нарушается: в зависимости от справедливости условия x>0 должна быть выведена одна или другая величина. Соответствующий фрагмент программы на C++ имеет вид:

    int x;
    cin >> x;
    if (x > 0)
    {
        cout << x;
    }
    else
    {
        cout << -x;
    }
    return 0;

В этой программе используется условная инструкция if (если). После слова if в обязательных круглых скобках указывается проверяемое условие (x > 0). После этого в фигурных скобках идет блок (последовательность) инструкций, который будет выполнен, если условие истинно, в нашем примере это вывод на экран величины x. Затем идет слово else (иначе) и после него блок инструкций, который будет выполнен, если проверяемое условие неверно, в данном случае будет выведено значение -x.

Итак, условная инструкция в C++ имеет следующий синтаксис:

    if (Условие)
    {
        Блок инструкций 1
    }
    else
    {
        Блок инструкций 2
    }

Блок инструкций 1 будет выполнен, если Условие истинно. Если Условие ложно, будет выполнен Блок инструкций 2.

В условной инструкции может отсутствовать слово else и последующий блок. Такая инструкция называется неполным ветвлением. Например, если дано число x и мы хотим заменить его на абсолютную величину x, то это можно сделать следующим образом:

    if (x < 0)
    {
        x = -x;
    }

В этом примере переменной x будет присвоено значение -x, но только в том случае, когда x<0.

Вложенные условные инструкции

Внутри условных инструкций можно использовать любые инструкции языка C++, в том числе и условную инструкцию. Получаем вложенное ветвление – после одной развилки в ходе исполнения программы появляется другая развилка. Покажем это на примере программы, которая по данным ненулевым числам x и y определяет, в какой из четвертей координатной плоскости находится точка (x,y):

    int x, y;
    cin >> x >> y;
    if (x > 0)
    {
        if (y > 0)   // x>0, y>0
        {
            cout << "Первая четверть" << endl;
        }
        else            // x>0, y<0
        {
            cout << "Четвертая четверть" << endl;
        }
    }
    else
    {
        if (y > 0)   // x<0, y>0
        {
            cout << "Вторая четверть" << endl;
        }
        else            // x<0, y<0
        {
            cout << "Третья четверть" << endl;
        }
    }

В этом примере мы использовали комментарии – текст, который компилятор игнорирует. Комментариями в C++ является последовательность символов // и весь текст после этого символа до конца строки. Обратите также внимание на отступы в начале строк, используемые для облегчения понимания текста.

Операторы сравнения

В качестве проверяемого условия должно использоваться выражение логического типа bool. Переменные логического типа принимают два значения: true (истина) и false (ложь). Также любое целочисленное выражение можно трактовать, как логическое выражение, при этом нулевое целое число означает ложь, а ненулевое — истину. Таким образом, если вместо условия написать false или 0, то оно будет всегда ложно, если же указать true, 1 или любое ненулевое число, то условие будет истинно.

Как правило, в качестве проверяемого условия используется результат вычисления одного из следующих операторов сравнения:

<
Меньше — возвращает true, если первый операнд меньше второго.
>
Больше — возвращает true, если первый операнд больше второго.
<=
Меньше или равно.
>=
Больше или равно.
==
Равенство. Возвращает true, если два операнда равны.
!=
Неравенство. Возвращает true, если два операнда неравны.

Например, условие (x * x < 1000) означает “значение x * x меньше 1000”, а условие (2 * x != y) означает “удвоенное значение переменной x не равно значению переменной y”.

Будьте аккуратны: оператор == (два знака равенства) — это проверка на равенство двух выражений, а оператор = (один знак равенства) — это присваивание одной переменной значения выражения и использование его в условии оператора ветвления в большинстве случаев является ошибкой.

Рассмотрим эту типичную ошибку на следующем примере:

    int a, b;
    cin >> a >> b;
    if (a = b)
    {
        cout << "Числа равны" << endl;
    }
    else
    {
        cout << "Числа не равны" << endl;
    }

Здесь по ошибке вместо операции сравнения == использована операция присваивания =. Поэтому при любых значениях a и b переменной a будет присвоено значение переменной b, при проверке истинности выражения a = b. Но оператор присваивания еще и возвращает значение, поэтому если значение b было ненулевым (а это интерпретируется, как истина), то программа выведет строку "Числа равны", а если нулевым — то строку "Числа не равны". При этом значение переменной a может быть вообще любым.

3.3 Логические операторы

Иногда нужно проверить одновременно не одно, а несколько условий. Например, проверить, является ли данное число четным можно при помощи условия (n % 2 == 0) (остаток от деления n на 2 равен 0), а если необходимо проверить, что два данных целых числа n и m являются четными, необходимо проверить справедливость обоих условий: n % 2 == 0 и m % 2 == 0, для чего их необходимо объединить при помощи оператора && (логическое И): n % 2 == 0 && m % 2 == 0.

В C++ существуют стандартные логические операторы: логическое И, логическое ИЛИ, логическое отрицание.

Логическое И является бинарным оператором (то есть оператором с двумя операндами: левым и правым) и имеет вид && (два знака амперсанда). Оператор && возвращает true тогда и только тогда, когда оба его операнда имеют значение true.

Логическое ИЛИ является бинарным оператором и возвращает true тогда и только тогда, когда хотя бы один операнд равен true. Оператор “логическое ИЛИ” имеет вид || (два знака вертикальной черты).

Логическое НЕ (отрицание) является унарным (то есть с одним операндом) оператором и имеет вид ! (восклицательный знак), за которым следует единственный операнд. Логическое НЕ возвращает true, если операнд равен false и наоборот.

Пример. Проверим, что хотя бы одно из чисел a или b оканчивается на 0:

    if (a % 10 == 0 || b % 10 == 0)

Проверим, что число a — положительное, а b — неотрицательное:

    if ( (a > 0) && !(b < 0) )

Или можно вместо !(b < 0) записать (b >= 0).

Другая типичная ошибка новичков — неверное использование двойных неравенств. Пусть нужно проверить, является ли введенное число ball корректной школьной оценкой, то есть числом от 1 до 5. Правильное решение такое:

    if (ball >= 1 && ball <= 5)

А вот такая запись будет синтаксически верной, но работать будет неправильно:

    if (1 <= ball <= 5)

Почему? Потому что в записи (1 <= ball <= 5) два оператора сравнения. Они выполняются слева направо и скобки между ними расставляются так: ( (1 <= ball) <= 5). Сначала выполняется первое сравнение: (1 <= ball). Его результатом будет значение типа bool, то есть либо 0, либо 1. А на втором действии результат вычисления предыдущего выражения (то если либо 0, либо 1) сравнивается с числом 5. Поэтому итоговый результат всегда будет истинным, независимо от значения числа ball.

Упражнения

3A: Високосный год

Дано натуральное число. Требуется определить, является ли год с данным номером високосным. Если год является високосным, то выведите YES, иначе выведите NO. Напомним, что в соответствии с григорианским календарем, год является високосным, если его номер кратен 4, но не кратен 100, а также если он кратен 400.

Эту задачу нужно решать при помощи логических операций.

Ввод Вывод
2010
NO

3B: Максимум трех чисел

Даны три целых числа. Найдите наибольшее из них (программа должна вывести ровно одно целое число).

Какое наименьшее число сравнений (>, <, >=, <=) нужно выполнить, для нахождения наибольшего из трех чисел? Решите задачу с использованием минимального числа сравнений.

Ввод Вывод
10
5
10
10

3C: Существует ли треугольник?

Даны три натуральных числа a, b, c. Определите, существует ли треугольник с такими сторонами. Если треугольник существует, выведите строку YES, иначе выведите строку NO.

Треугольник — не должен быть вырожденным, то есть вершины треугольника не лежат на одной прямой.

Ввод Вывод
5
3
2
NO

3D: Сколько совпадает чисел

Даны три целых числа. Определите, сколько среди них совпадающих. Программа должна вывести одно из чисел: 3 (если все совпадают), 2 (если два совпадает) или 0 (если все числа различны).

Ввод Вывод
10
5
10
2

3E: Ход ладьи

Шахматная ладья ходит по горизонтали или вертикали. Даны две различные клетки шахматной доски, определите, может ли ладья попасть с первой клетки на вторую одним ходом. Программа получает на вход четыре числа от 1 до 8 каждое, задающие номер столбца и номер строки сначала для первой клетки, потом для второй клетки. Программа должна вывести YES, если из первой клетки ходом ладьи можно попасть во вторую или NO в противном случае.

Для простоты можно не рассматривать случай, когда данные клетки совпадают.

Ввод Вывод
1
1
1
8
YES
3
4
4
3
NO

3F: Ход короля

Решите аналогичную задачу для короля, который может ходить в клетку, которая является соседней с данной по стороне или углу.

Для простоты можно не рассматривать случай, когда данные клетки совпадают.

Ввод Вывод
1
1
2
2
YES
1
1
3
3
NO

3G: Ход слона

Решите аналогичную задачу для слона, который ходит по диагонали.

Для простоты можно не рассматривать случай, когда данные клетки совпадают.

Ввод Вывод
1
1
8
8
YES
1
1
1
2
NO

3H: Ход коня

Решите аналогичную задачу для коня, который ходит буквой “Г” — на две клетки по вертикали в любом направлении и на одну клетку по горизонтали, или наоборот.

Ввод Вывод
1
1
2
3
YES
1
1
3
3
NO

3I: Шахматная доска

Заданы две клетки шахматной доски. Если они покрашены в один цвет, то выведите слово YES, а если в разные цвета – то NO.

Ввод Вывод
1
1
8
8
YES
1
1
1
8
NO

4A: Коровы

Для данного числа n<100 закончите фразу “На лугу пасется...” одним из возможных продолжений: “n коров”, “n корова”, “n коровы”, правильно склоняя слово “корова”. Программа должна вывести введенное число n и одно из слов: korov, korova или korovy. Между числом и словом должен стоять ровно один пробел.

Ввод Вывод
1
1 korova
2
2 korovy
5
5 korov

4B: Тип треугольника

Даны три стороны треугольника a, b, c. Определите тип треугольника с заданными сторонами. Выведите одно из четырех слов: rectangular для прямоугольного треугольника, acute для остроугольного треугольника, obtuse для тупоугольного треугольника или impossible, если треугольника с такими сторонами не существует.

Ввод Вывод
1
1
1
acute
3
4
5
rectangular

4C: Билеты на метро

Давным-давно билет на одну поездку в метро стоил 15 рублей, билет на 10 поездок стоил 125 рублей, билет на 60 поездок стоил 440 рублей. Пассажир планирует совершить n поездок. Определите, сколько билетов каждого вида он должен приобрести, чтобы суммарное количество оплаченных поездок было не меньше n, а общая стоимость приобретенных билетов — минимальна.

Программа получает на вход одно число n и должна вывести три целых числа, равных необходимому количеству билетов на 1, на 10, на 60 поездок.

Ввод Вывод
85
5 2 1
19
0 2 0

4D: Упорядочить три числа

Дано три числа. Упорядочите их в порядке неубывания. Программа должна считывать три числа a, b, c, затем программа должна менять их значения так, чтобы стали выполнены условия a <= b <= c, затем программа выводит тройку a, b, c.

Дополнительные ограничения: нельзя использовать дополнительные переменные. Единственной разрешенной операций является обмен двух переменных. Его просто делать при помощи функции swap из файла algorithm: для обмена двух переменных можно вызвать swap(a, b), при этом программа должна быть на языке C++ и в начале программы необходимо написать #include<algorithm> и using namespace std;.

Какое наименьшее число сравнений необходимо для решения этой задачи? Почему нельзя обойтись меньшим числом сравнений?

Ввод Вывод
1
2
1
1 1 2

4E: Яша плавает в бассейне

Яша плавал в бассейне размером \(N\times M\) метров и устал. В этот момент он обнаружил, что находится на расстоянии x метров от одного из длинных бортиков (не обязательно от ближайшего) и y метров от одного из коротких бортиков. Какое минимальное расстояние должен проплыть Яша, чтобы выбраться из бассейна на бортик?

Программа получает на вход числа \(N\), \(M\), \(x\), \(y\). Программа должна вывести число метров, которое нужно проплыть Яше до бортика.

Ввод Вывод
10
25
7
8
3

4F: Пересадки

На Новом проспекте для разгрузки было решено пустить два новых автобусных маршрута на разных участках проспекта. Известны конечные остановки каждого из автобусов. Определите количество остановок, на которых можно пересесть с одного автобуса на другой.

Вводятся четыре числа – номера конечных остановок сначала первого, потом второго автобуса.

Ваша программа должна выводить одно число – искомое количество остановок.

Ввод Вывод
3
6
4
2
2
3
1
5
10
0

4G: Узник замка Иф

За многие годы заточения узник замка Иф проделал в стене прямоугольное отверстие размером D×E. Замок Иф сложен из кирпичей, размером A×B×C. Определите, сможет ли узник выбрасывать кирпичи в море через это отверстие, если стороны кирпича должны быть параллельны сторонам отверстия.

Программа получает на вход числа A, B, C, D, E и должна вывести слово YES или NO.

Ввод Вывод
2
1
3
2
2
YES
1
2
3
1
1
NO

4H: Коробки

Есть две коробки, первая размером A1×B1×C1, вторая размером A2×B2×C2. Определите, можно ли разместить одну из этих коробок внутри другой, при условии, что поворачивать коробки можно только на 90 градусов вокруг ребер.

Программа получает на вход числа A1, B1, C1, A2, B2, C2. Программа должна вывести одну из следующих строчек:
Boxes are equal, если коробки одинаковые,
The first box is smaller than the second one, если первая коробка может быть положена во вторую,
The first box is larger than the second one, если вторая коробка может быть положена в первую,
Boxes are incomparable, во всех остальных случаях.

Ввод Вывод
1
2
3
3
2
1
Boxes are equal
3
4
5
2
4
6
Boxes are incomparable

5A: Билеты на метро — 2

Решите задачу “Билеты на метро” при наличии следующих билетов: 1 поездка — 15 рублей, 5 поездок — 70 рублей, 10 поездок — 125 рублей, 20 поездок — 230 рублей, 60 поездок — 440 рублей.

Программа получает на вход одно число n и должна вывести пять целых чисел: количество билетов на 1, 5, 10, 20, 60 поездок, которое необходимо приобрести. Если для какого-то данного n существует несколько способов приобретения билетов одинаковой суммарной стоимости, необходимо вывести ту комбинацию билетов, которая дает большее число поездок.

5B: Складирование ноутбуков

На склад, который имеет форму прямоугольного параллелепипеда, привезли ноутбуки, упакованные в коробки. Каждая коробка также имеет форму прямоугольного параллелепипеда. По правилам хранения коробки с ноутбуками должны быть размещены на складе с выполнением следующих двух условий:
1. Стороны коробок должны быть параллельны сторонам склада.
2. Коробку при помещении на склад разрешается расположить где угодно (с выполнением предыдущего условия), в том числе на другой коробке, но все коробки должны быть ориентированы одинаково (т.е. нельзя одну коробку расположить “стоя”, а другую —“лежа”)

Напишите программу, которая по размерам склада и размерам коробки с ноутбуком определит максимальное количество ноутбуков, которое может быть размещено на складе. Программа получает на вход шесть натуральных чисел. Первые три задают длину, высоту и ширину склада. Следующие три задают соответственно длину, высоту и ширину коробки с ноутбуком. Программа должна вывести одно число — максимальное количество ноутбуков, которое может быть размещено на складе.

Ввод Вывод
100
200
300
1
2
3
1000000
100
200
300
3
2
1
1000000
100
100
1
2
2
2
0
7
7
7
3
3
3
8

5C: Два прямоугольника

Петя нарисовал на клетчатом листке бумаги красивый рисунок прямоугольной формы. Его младшему брату Васе тоже захотелось порисовать, поэтому он вырезал из того же листка бумаги другой прямоугольник. При этом он не делал лишних разрезов, то есть в результате в листке осталась прямоугольная дырка. Кроме того, линии разреза не проходили (даже частично) по границам рисунка Пети. Более того, по границам рисунка не проходили даже продолжения линий разреза.

Ваша задача – по данным о расположении рисунка и прямоугольной дырки определить, испортил ли Вася рисунок старшего брата, другими словами, есть ли на вырезанном Васей прямоугольнике хотя бы маленький фрагмент рисунка Пети.

Вам даны 8 целых чисел — \(x_1\), \(y_1\), \(x_2\), \(y_2\), \(x_3\), \(y_3\), \(x_4\), \(y_4\), где \((x_1, y_1)\) — координаты левого нижнего угла рисунка Пети, \((x_2, y_2)\) — координаты правого верхнего угла рисунка. Аналогично, \((x_3, y_3)\) — координаты левого нижнего угла вырезанного Васей прямоугольника, \((x_4, y_4)\) — координаты правого верхнего угла вырезанного прямоугольника. Гарантируется, что данные прямоугольники невырождены (\(x_1 \lt x_2\), \(y_1 \lt y_2\) и аналогичные неравенства для второго набора координат).

Выведите YES, если Вася испортил рисунок, и NO в противном случае.

Тесты к этой задаче закрытые.

Ввод Вывод
1
1
2
2
3
3
4
4
NO
1
1
3
3
2
2
4
4
YES
1
1
4
4
2
2
3
3
YES

5D: Расстановка ноутбуков

В школе решили на один прямоугольный стол поставить два прямоугольных ноутбука.

Ноутбуки нужно поставить так, чтобы их стороны были параллельны сторонам стола.

Определите, какие размеры должен иметь стол, чтобы оба ноутбука на него поместились, и площадь стола была минимальна.

Вводится четыре натуральных числа, первые два задают размеры одного ноутбука, а следующие два — размеры второго. Числа не превышают 1000.

Выведите два числа — размеры стола. Если возможно несколько ответов, выведите любой из них (но только один).

Тесты к этой задаче закрытые.

Ввод Вывод
10
2
2
10
10 4
5
7
3
2
5 9

5E: Римские числа

Дано натуральное число \(N\) от 1 до 3999. Выведите его запись римскими цифрами.

Ввод Вывод
179
CLXXIX