Очень рад, что идея форума на сайте оказалась вам
по душе. Кстати, теперь некоторые дискуссии из
рассылки можно перенести на форум. Например,
ответ на свой вопрос в 23# Korotkiy Sergey запросто сможет
найти в теме [ПОМОГИТЕ!!!!!].
Письма читателей:
Письма в данный раздел отбираются по усмотрению
автора рассылки, интересные для большого круга
подписчиков. Хочу предупредить, что
корреспонденция, оскорбляющая чьё-либо
достоинство или содержащая нецензурные
выражения публикации не подлежит.
From:
Z.M. <zhilinmike@hotmail.com>
To: sapisoft@yandex.ru
Date: Tuesday, March 19, 2002, 9:56:46 PM
Subject:
Здравствуйте.
Я очень хорошо изучаю вашу рассылку. Она
просто класс!!! Но порой данные решения такие
тупые. Вот последняя задача - последовательность.
Решение перебором на мой взгляд очень сложное и
неоправданное. Просто динамика решает её очень
хорошо.
Вот что я сотворил за полчаса после прочтения
письма. Как говорится проще надо-проще!!!!!
Mike.
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
uses crt,dos;
var dat,max,sol:array[1..200]of longint;
n:integer;
procedure inputdata; {input data}
var i:integer;
begin
clrscr;
assign(input,'input.txt');
reset(input);
readln(n);
for i:=1 to n do readln(dat[i]);
close(input);
end;
procedure find;
var i,j,m:integer;
begin
max[1]:=1;
for i:=2 to n do begin
m:=0;
for j:=1 to i-1 do if (dat[i]>=dat[j])and(max[j]>m)then
m:=max[j];
max[i]:=m+1;
end;
end;
procedure outresult;
var i,m,mm:integer;
begin
m:=0;
for i:=1 to n do if max[i]>m then m:=max[i];
assign(output,'output.txt');
rewrite(output);
writeln(m);
mm:=m;
for i:=n downto 1 do if max[i]=m then begin sol[m]:= dat[i];dec(m) end;
for i:=1 to mm do writeln(sol[i]);
close(output);
end;
begin
inputdata;
find;
outresult;
end.
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Алексей
Шамис: Да, это
конечно все хорошо, но почему ваше решение не
проходит по тесту, данному в условии?;)
From:
Igor L.Zubrytsky <igorz@butes.west.energy.gov.ua>
To: sapisoft@yandex.ru
Date: Monday, March 18, 2002, 8:55:30 AM
Subject: Ошибка в теории (немного математики от 18.3.2002)
Если две прямые перпендикулярны, то K1*K2= -1 , а не 1.
Пример: y=x, y=-x. k1*k2=1*(-1)=-1 .
Алексей
Шамис: В
предыдущем номере действительно была допущенна
ошибка (или, если позволите, опечатка) в разделе
"теория". Но странно, что отреагировал на это
только один человек...8)
From:
Serhiy Serbin <serhiys@adarvo.com>
To: sapisoft@yandex.ru
Date: Tuesday, March 19, 2002, 9:40:55 AM
Subject: задача
Коль пошел разговор об уравнении прямой, то
вспомнил очень простую задачу из какойто то там
олимпиады. Задача действительно очень простая,
правда не совсем понятно почему, но решили ее
тогда далеко не все.
Задана последовательность точек на плоскости,
парами координат (x,y). Колличество точек N >= 3.
Начинаем последовательно просматривать тройки
точек от 1 до N-2. Будем считать, что был
осушевствлен левый поворот, если луч исходящий
из точки (i+1) в точку (i+2) был повернут против
часовой стрелки по отношению, к лучу из i в (i+1). И
соотвественно правым поворотом, если по часовой
стрелке. Задание: сколько левых повортов в
последовательности?
К сожалению или к радости, именно подобная
формулировка была в задании, что сразу несет кучу
вопросов. Ну для начала, можно уверенно всегда
выдавать ответ ноль и это всегда будет
правильным решением, но что бы привесте задачу к
тому
виду, который по видимому подразумевали авторы, я
от себя добавлю два уточнения.
Если луч (i+1 -> i+2) продолжает луч (i - > i+1) (поворот
на ноль градусов) - будем считать ни левым ни
правым. И самое главное, всегда во внимание будем
принимать меньшый угол, который образуется между
лучами.
Best regards,
Serhiy Serbin
From:
Yuri Y. Roumega <ryy@mail.ru>
To: "Aleksey Shamis" <sapisoft@yandex.ru>
Date: Wednesday, March 20, 2002, 1:28:29 AM
Subject: По материалам выпуска #24 рассылки
"Олимпиадные задачи с решениями на TP"
Здравствуйте, Aleksey,
Я часто и с интересом читаю Вашу рассылку, но
обидно, что наравне с интересной информацией в
ней иногда бывают весьма сомнительные, а то и
неправильные утверждения.
В выпуске #24 Алексей Ильичёв пишет, что при обмене
значений 2 переменных c помощью XOR алгоритм будет
работать некорректно, если A=B. Это не так. В самом
деле, рассмотрим значения переменных на каждом
шаге:
Действительно, после 1-го шага A обнулится, но это
не означает, что в итоге (после 3-го шага) A будет
равно 0 - вопреки словам Алексея.
Второе замечание касается ур-ния прямой в 2D.
Было сказано, что любая прямая на плоскости
задается уравнением Y=K*X+B . На самом деле не все
прямые можно задать таким ур-нием. Рассмотрите
прямую, параллельную оси ординат. Тогда у всех
точек X=const, а Y меняется от -oo до +oo. Естественно,
нельзя подобрать K и B такие, чтобы ур-ние Y=K*X+B
описывало линию.
Для задания произвольной прямой на плоскости
следует использовать ур-ние A*X+B*Y+C=0. К примеру, для
прямой, проходящей
через точки (x1,y1) и (x2,y2) A, B и С будут вычисляться
так:
A:=y1-y2;
B:=x2-x1; {это не ошибка!}
C:=(x1*y2)-(x2*y1);
Тогда, если есть 2 прямые A1*X+B1*Y+C1=0 и A2*X+B2*Y+C2=0, то
условие параллельности: A1*B2=A2*B1 условие
перпендикулярности: A1*A2=-B1*B2.
C уважением,
Yuri.
From:
Hilary <lars@ezmail.ru>
To: sapisoft@yandex.ru
Date: Monday, March 18, 2002, 5:11:49 PM
Subject: Проблемка...
Добрый день!
Возникла небольшая проблема (хотя, может это
только для меня?)
Задача: вычислить на Паскале число е с
точностью до 8-9 знака.
Но: дело в том что при "чистом" использовании
второго замечательного предела(это который
(1+1/n)^n)) или формулы разложения в ряд Тейлора
точность достигается в 7 знаке, а дальше
начинается чертовщина, в виде появления цифры 3
вместо 2. Была бы благодарна, если бы хоть
кто-нибудь пояснил мне причину сих происков
судьбы, а так же не отказалась бы от идей по
поводу достижения цели (8-9 знаков после запятой...)
Hilary.
mailto:lars@ezmail.ru
ЗАДАЧИ
Игра в города (4
уровень)
Условие:
Всем известны правила игры "в города":
первый игрок называет произвольный город,
следующий - город, название которого начинается
на ту же букву, на которую заканчивается название
предыдущего города, и т.д. Аналогичным образом
можно
играть не в названия городов, а, например, в
названия животных.
Задан список допустимых для описанной игры слов,
слова в нём могут повторяться. Напишите
программу, определяющую, в каком порядке в
процессе игры должны быть названы слова из
списка, чтобы каждое слово было использовано
ровно столько раз,
сколько оно в нём встречается.
Технические
требования:
Входные данные:
Во входном файле на первой строке записано число
N - количество слов в списке (1<=N<=1000), а в
последующих N строках - сами слова. Каждое из них
является последовательностью не более, чем 10
строчных английских букв.
Выходные данные:
Выведите в выходной файл слова в исходном
порядке, либо сообщение "NO", если такого
порядка не существует. Каждое слово должно быть
выведено в отдельную строку выходного файла.
Если построить граф, в котором буквы английского
алфавита являются вершинами, а данные нам слова -
рёбрами, то задача сведётся к построению
Эйлерова пути в ориентированном графе.
Как изменится условие существования Эйлерова
пути для ориентированного графа? Нетрудно
понять, что для существования в ориентированном
графе Эйлерова пути необходимо и достаточно,
чтобы для каждой вершины кол-во входящих рёбер
равнялось кол-ву выходящих, или для одной вершины
кол-во входящих рёбер было больше на 1, а для
другой кол-во выходящих было больше на 1.
При этом каждое ребро должно быть достижимым, то
есть нет вершины, к которой подходит ребро и к
которой нет пути из стартовой вершины.
Собственно алгоритм построения пути тот же
самый, что и для неориентированного графа, зы
стартовую вершину принимается вершина, для
которой кол-во выходящих рёбер на 1 больше.
var
n, i, j : integer;
wrd : array[1..1000] of string[10]; {Тут храним слова}
rin, rout, {Кол-во входящих и выходящих рёбер}
hash : array[1..26] of integer; {указатель на элемент
массива рёбер,
с которого начинаются рёбра, выходящие из
данной вершины}
s, f : array[0..1000] of integer; {список рёбер - номера
начальных и конечных вершин}
sv, fv, {начальная и конечная вершины}
v : integer;
avail : array[1..26] of boolean; {существует ли путь из
стартовой вершины в данную}
way, ret : array[0..1000] of integer; {очередь рёбер}
deleted : array[1..1000] of boolean; {отмечаем уже
использованные слова}
found : boolean;
procedure swap(i, j : integer);
var
st : string[10];
w : integer;
begin
w := s[i];
s[i] := s[j];
s[j] := w;
w := f[i];
f[i] := f[j];
f[j] := w;
st := wrd[i];
wrd[i] := wrd[j];
wrd[j] := st;
end;
procedure sort(l, r : integer);
var
x, i, j : integer;
begin
i := l;
j := r;
x := s[(l + r) div 2];
repeat
while s[i] < x do inc(i);
while s[j] > x do dec(j);
if i <= j then begin
swap(i, j);
inc(i);
dec(j);
end;
until i > j;
if i < r then sort(i, r);
if j > l then sort(l, j);
end;
procedure check(v : integer);
var
i : integer;
begin
avail[v] := true;
i := hash[v];
while (s[i] = v) do begin
if not avail[f[i]] then check(f[i]);
inc(i);
end;
end;
procedure movefrom(v : integer);
var
i : integer;
found : boolean;
begin
ret[0] := 0;
repeat
found := false;
i := hash[v];
while (s[i] = v) and (deleted[i]) do inc(i);
if s[i] = v then begin
found := true;
deleted[i] := true;
inc(ret[0]);
ret[ret[0]] := i;
v := f[i];
end;
until not found;
end;
begin
assign(input, 'input.txt');
reset(input);
readln(n);
for i := 1 to n do begin
readln(wrd[i]);
s[i] := ord(wrd[i, 1]) - ord('a') + 1;
f[i] := ord(wrd[i, length(wrd[i])]) - ord('a') + 1;
inc(rout[s[i]]);
inc(rin[f[i]]);
end; {читаем данные, считаем кол-во подходящих
рёбер для каждой вершины}
close(input);
sort(1, n); {сортируем рёбра по начальной вершине}
for i := 1 to 26 do
if (rout[i] - rin[i] = 1) and (sv = 0) then sv := i
else if (rin[i] - rout[i] = 1) and (fv = 0) then fv := i
else if (rout[i] <> rin[i]) then begin
assign(output, 'output.txt');
rewrite(output);
writeln('NO');
close(output);
halt;
end; {Проверяем первое условие существования
пути, записываем
стартовую и конечную вершины}
for i := 1 to n do if hash[s[i]] = 0 then hash[s[i]] := i; {формируем
массив указателей на элементы списка рёбер
для каждой вершины}
if sv = 0 then for i := 1 to 26 do if rout[i] > 0 then sv := i; {если
стартовую вершину найти не удалось, берём
произвольную}
check(sv); {обходом в глубину закрашиваем
компоненту связности,
к которой относится первая вершина}
for i := 1 to 26 do if (not avail[i]) and (rin[i] > 0) then begin
assign(output, 'output.txt');
rewrite(output);
writeln('NO');
close(output);
halt;
end; {если не все рёбра достижимы, значит пути
нет}
v := sv;
repeat
found := false;
i := hash[v];
while (s[i] = v) and deleted[i] do inc(i);
if s[i] = v then begin
found := true;
inc(way[0]);
way[way[0]] := i;
deleted[i] := true;
v := f[i];
end;
until not found; {идём от стартовой вершины, пока не
упрёмся в конечную}
v := sv;
i := 0;
while i <= way[0] do begin
if rout[v] > 0 then begin
movefrom(v);
for j := way[0] downto i + 1 do way[j + ret[0]] := way[j];
inc(way[0], ret[0]);
move(ret[1], way[i+1], ret[0] shl 1);
end;
inc(i);
v := f[way[i]];
end; {добавляем к нашему пути все возможные
циклы}
assign(output, 'output.txt');
rewrite(output);
for i := 1 to way[0] do writeln(wrd[way[i]]); {выводим ответ}
close(output);
end.
Если нужна дополнительная информация, такая
например как теорема Эйлера с доказательством,
или алгоритм построения Эйлерова пути - пишите.
Кстати. Программы гораздо лучше читаются, если
они написаны с отступами в нужных местах ;-)
ТЕОРИЯ
Немного
математики...[2]
В продолжение
затронутой темы. Думаю всем еще с 8 класса
известна формула Герона (для вычисления площади
треугольника):
S = sqrt(p*(p-a)*(p-b)*(p-c)), где p - полупериметр
треугольника со сторонами a, b и с.
Но часто требуется найти площадь
треугольника по заданным координатам его вершин.
В этом случае может пригодиться следующая
формула:
S =
abs(((x1-x0)*(y2-y0)-(x2-x0)*(y1-y0))/2).
Если у вас есть
интересная информация для данной рубрики -
пишите: sapisoft@yandex.ru.
ТЕМЫ ФОРУМА:
7. Anton [Системы линейных
уравнений] 25-Мар (18:15)