Задачи на пересечение областей (C1): «на стыке алгебры и логики» Д.Ю. Усенков, О.Б. Богомолова Задача С1 (2011 г.) Требовалось написать программу, при выполнении которой с клавиатуры считываются координаты точки на плоскости (x,y – действительные числа) и определяется принадлежность этой точки заданной заштрихованной области (включая границы). Программист торопился и написал программу неправильно. ПРОГРАММА НА ПАСКАЛЕ var x,y: real; begin readln(x,y); if y<=x then if y<=-x then if y>=x*x-2 then write('принадлежит') else write('не принадлежит') end. ПРОГРАММА НА БЕЙСИКЕ INPUT x, y IF y<=x THEN IF y<=-x THEN IF y>=x*x-2 THEN PRINT "принадлежит" ELSE PRINT "не принадлежит" ENDIF ENDIF ENDIF END ПРОГРАММА НА СИ void main(void) { float x,y; scanf("%f%f",&x,&y); if (y<=x) if (y<=-x) if (y>=x*x-2) printf("принадлежит"); else printf("не принадлежит"); } Последовательно выполните следующее: 1) Приведите пример таких чисел x, y, при которых программа неправильно решает поставленную задачу. 2) Укажите, как нужно доработать программу, чтобы не было случаев ее неправильной работы. (Это можно сделать несколькими способами, поэтому можно указать любой правильный способ доработки исходной программы). Решение: всё, что ниже графика – условие «y f(x)» y всё, что выше графика – условие «y f(x)» y = f(x) всё, что левее графика – условие «x f -1(y)» всё, что правее графика – условие «x f -1(y)» x y = f(x) Решение: y y = x2 - 2 0 xx y = -x y=x y=x ( y x2 – 2 AND y -x ) OR y = -x (y x2 – 2 AND y x ) Решение: var x,y: real; begin readln(x,y); if y<=x then if y<=-x then if y>=x*x-2 then write('принадлежит') else write('не принадлежит') end. 1. В цепочке последовательных операторов if ветвь else всегда относится к последнему if. 2. Цепочка последовательных if ... then эквивалентна записи одного if с условиями, записанными через AND. if (y<=x) AND (y<=-x) AND write('принадлежит') else write('не принадлежит') (y>=x*x-2) then Но это условие – неверное! Будем искать правильное Решение: if (y<=x) AND (y<=-x) AND write('принадлежит') else write('не принадлежит') (y>=x*x-2) then y условие «y f(x)» – всё, что ниже графика условие «y f(x)» – всё, что выше графика условие «x f-1(y)» – всё, что левее графика условие «x f-1(y)» – всё, что правее графика AND – пересечение областей, OR – объединение областей y = x2 - 2 0 x 1 2 y=x y = -x Области 1 и 2 – точки, которые программа обрабатывает ошибочно Решение: Области 1 и 2 – точки, которые программа обрабатывает ошибочно y 2 1 (-2, 2) y = x2 - 2 (2, 2) Пример точки, обрабатываемой ошибочно 0 x (- 2 , 0) (-1, -1) ( 2 , 0) y=x (0, -2) y = -x (1, -1) Решение: Ошибочная программа var x,y: real; begin readln(x,y); if y<=x then if y<=-x then if y>=x*x-2 then write('принадлежит') else write('не принадлежит') end. Правильная программа var x,y: real; begin readln(x,y); if y<=x then if y<=-x then if y>=x*x-2 then write('принадлежит') else write('не принадлежит') end. if (y>=x*x-2 AND y<=-x) OR (y>=x*x-2 AND y<=x) then (y x2 – 2 AND y -x) OR (y x2 – 2 AND y x) Задача С1 (2009 г.) Требовалось написать программу, при выполнении которой с клавиатуры считываются координаты точки на плоскости (x,y – действительные числа) и определяется принадлежность этой точки заданной заштрихованной области (включая границы). Программист торопился и написал программу неправильно. ПРОГРАММА НА ПАСКАЛЕ var x,y: real; begin readln(x,y); if y<=1 then if x>=0 then if y>=sin(x) then write('принадлежит') else write('не принадлежит') end. ПРОГРАММА НА БЕЙСИКЕ INPUT x, y IF y<=1 THEN IF x>=0 THEN IF y>=SIN(x) THEN PRINT "принадлежит" ELSE PRINT "не принадлежит" ENDIF ENDIF ENDIF END ПРОГРАММА НА СИ void main(void) { float x,y; scanf("%f%f",&x,&y); if (y<=1) if (x>=0) if (y>=sin(x)) printf("принадлежит"); else printf("не принадлежит"); } Последовательно выполните следующее: 1) Приведите пример таких чисел x, y, при которых программа неправильно решает поставленную задачу. 2) Укажите, как нужно доработать программу, чтобы не было случаев ее неправильной работы. (Это можно сделать несколькими способами, поэтому можно указать любой правильный способ доработки исходной программы). Задача С1 (2010 г.) Требовалось написать программу, при выполнении которой с клавиатуры считываются координаты точки на плоскости (x,y – действительные числа) и определяется принадлежность этой точки заданной заштрихованной области (включая границы). Программист торопился и написал программу неправильно. ПРОГРАММА НА ПАСКАЛЕ var x,y: real; begin readln(x,y); if x*x+y*y>=4 then if x>= –2 then if y<= –x then write('принадлежит') else write('не принадлежит') end. ПРОГРАММА НА БЕЙСИКЕ INPUT x, y IF x*x+y*y>=4 THEN IF x>= –2 THEN IF y<= –x THEN PRINT "принадлежит" ELSE PRINT "не принадлежит" ENDIF ENDIF ENDIF END ПРОГРАММА НА СИ void main(void) { float x,y; scanf("% f % f",&x,&y); if (x*x+y*y>=4) if (x>= –2) if (y<= –x) printf("принадлежит"); else printf("не принадлежит"); } Последовательно выполните следующее: 1) Приведите пример таких чисел x, y, при которых программа неправильно решает поставленную задачу. 2) Укажите, как нужно доработать программу, чтобы не было случаев ее неправильной работы. (Это можно сделать несколькими способами, поэтому можно указать любой правильный способ доработки исходной программы).