разбор задач

Download Report

Transcript разбор задач

Муниципальный этап
всероссийской олимпиады
школьников по информатике
2013-2014 учебный год
1
7-8 классы
При выполнении заданий для
школьников 7-8 классов
использование компьютеров не
допускается
2
Задача 1. ВЛОСО (5 баллов)
Какое слово лишнее?
1) ЗОН БИ2) ЧИРПИ К 3) РАВОКО 4) ФАРЖИ
Анаграммы
3
Задача 2. Сумма16 (5 баллов)
Сумму шестнадцатеричных чисел
АВ+АВ00+АВ0000+....+АВ00000000 перевели в
восьмеричную систему счисления. В этом
восьмеричном числе найдите десятую цифру
слева.
4
Решение:
АВ+АВ00+АВ0000+....+АВ00000000= АВАВАВАВАВ
АВАВАВАВАВ
10101011…10101011
10 знаков
40 знаков
40 div 3 =13
40 mod 3 =1
Первый 16-ричный символ дает два 8-ричных знака. Каждые
последующиетри 16-ричных символа дают четыре 8-ричных.
А ВАВ АВА ВАВ
Десятым 8-ричным знаком
будут последние три 2-ных знака
4 16-ричного числа А.
2
4
А16 =10102
0102=28
5
Задача 3. Крипторифм (15 баллов)
Крипторифм – это математический ребус, в
котором одинаковые цифры шифруются одной и
той же буквой, а разным цифрам соответствуют
различные буквы. Считается, что никакое число
не должно начинаться с нуля. Замените буквы
цифрами, чтобы получилось верное выражение.
Р
Ю
М
К
А
+
Р
Ю
М
К
А
А
В
А
Р
И
Я
6
Решение:
5-значное число + 5-значное число = 6-значное число
Крайняя левая цифра =1, т.е. А =1
А + А =Я, т.е. Я=2; Ю +Ю =А, т.е. М>5, Ю =0 или Ю =5,
И - четное
Р Ю М К А
+ Р Ю М К А
А В А Р И Я
8 5 9 3 1
+ 8 5 9 3 1
1 7 1 8 6 2
7
Задача 4. Блок-схема (15 баллов)
Определите и укажите в ответе, какое
значение переменной R будет на выходе.
(Операция X mod K вычисляет остаток от
деления первого аргумента X на второй
аргумент K. Например, 6 mod 2 = 0, 7 mod 2 =
1, 1 mod 2 = 1).
8
9
№
п/п
1
Команда
A=7; B=6; R=1; K=11
Переменные
Условие
A
B
K
R
7
6
11
1
2
6>0 (да)
3
6 mod 3 = 0
4
B=B/3; A=(A*A*A) mod K
2
2
5
2>0 (да)
6
2 mod 3 = 2
7
B=B-2; R=(A*R*A) mod K
0
4
8
9
0>0 (нет)
Вывод R
4
Ответ: 4
10
Задача 5. Basic_1 (20 баллов)
В этой программе вводятся некоторые значения переменных A и D.
INPUT “A=”,A
INPUT “D=”,D
FOR N = 3 TO 7 STEP 2
B=A
S=B
FOR K = 1 TO N
B=B+D
S=S+B
NEXT K
PRINT S;", "
NEXT N
Нужно определить пропущенный член последовательности 28, …, 24.
11
INPUT “A=”,A
INPUT “D=”,D
FOR N = 3 TO 7 STEP 2
B=A
S=B
FOR K = 1 TO N
B=B+D
S=S+B
NEXT K
PRINT S;", "
NEXT N
N
N=3
K
A
A+D
2A+D
A+2D
3A+3D
A+3D
4A+6D
2
B=B+D; S=S+B
K=3
A
1
B=B+D; S=S+B
K=2
S
3
B=A; S=B
K=1
B
3
B=B+D; S=S+B
4A+6D = 28
12
INPUT “A=”,A
INPUT “D=”,D
FOR N = 3 TO 7 STEP 2
B=A
S=B
FOR K = 1 TO N
B=B+D
S=S+B
NEXT K
PRINT S;", "
NEXT N
N
N=5
K
B=B+D; S=S+B
2A+D
A+2D
3A+3D
A+3D
4A+6D
A+4D
5A+10D
A+5D
6A+15D
4
B=B+D; S=S+B
K=5
A+D
3
B=B+D; S=S+B
K=4
A
2
B=B+D; S=S+B
K=3
A
1
B=B+D; S=S+B
K=2
S
5
B=A; S=B
K=1
B
5
6A+15D = ?
13
N
INPUT “A=”,A
INPUT “D=”,D
FOR N = 3 TO 7 STEP 2
B=A
S=B
FOR K = 1 TO N
B=B+D
S=S+B
NEXT K
PRINT S;", "
NEXT N
N=7
K
8A+28D = 24
B=B+D; S=S+B
3A+3D
A+3D
4A+6D
A+4D
5A+10D
A+5D
6A+15D
A+6D
7A+21D
A+7D
8A+28D
6
B=B+D; S=S+B
K=7
A+2D
5
B=B+D; S=S+B
K=6
2A+D
4
B=B+D; S=S+B
K=5
A+D
3
B=B+D; S=S+B
K=4
A
2
B=B+D; S=S+B
K=3
A
1
B=B+D; S=S+B
K=2
S
7
B=A; S=B
K=1
B
6
14
4A+6D=28
8A+28D=24
A=10 D=-2
6A+15D = 30
Ответ: 30
15
Задача 6. Basic_2 (20 баллов)
Определить значение переменной S, вычисленное в
программе.
N=3: DIM A(N),P(N): A(0)=8: A(1)=5: A(2)=9: A(3)=1: P(0)=0
FOR L=1 TO N
P(L)=L
IF A(P(L-1)) > A(P(L)) THEN R=P(L-1): P(L-1)=P(L): P(L)=R
NEXT L
S=0
FOR L=0 TO N
S = S + S*N + P(L) - L
NEXT L
PRINT”S=”;S
16
N
L
S R
A
P
Условие
0 1 2 3 0 1 2 3
8 5 9 3 0
1
1
0
2
A(P(L-1))>A(P(L))
A(P(0))>A(P(1)
A(0)>A(1)
8>5 (да)
1 0
2
3
A(P(L-1))>A(P(L))
A(P(1))>A(P(2)
A(0)>A(2)
8>9 (нет)
3
A(P(L-1))>A(P(L))
A(P(2))>A(P(3)
A(2)>A(3)
9>3 (да)
2
3 2
17
N
L
S R
A
P
Условие
0 1 2 3 0 1 2 3
3
8 5 9 3 1 0 3 2
0
0
1
1
3
2 13
3 51
Ответ: 51
18
Задача 7. Pascal (20 баллов)
Pascal_1. Определить значение переменной Y, вычисленное в программе.
(Операция X div K – целочисленное деление первого аргумента X на второй
аргумент K. Например, 6 div 2 = 3, 7 div 2 = 3).
Program Pascal_1;
Type Table = Array [0..2, 0..2] Of Integer;
Const T: Table=((2,1,0),(0,2,1),(1,0,2));
Var S, Y, X: Integer;
Begin
S:=0; Y:=0; X:=12;
While X>0 Do Begin
S:= T[S, X mod 3];
Y:= Y*3 + S;
X:= X div 3;
End;
WriteLn('Y=',Y);
End.
19
Команда
S
Y
X
2
1
0
S:=0; Y:=0; X:=12;
0
0
12
0
2
1
S:= T[S, X mod 3];
2
1
0
2
Y:= Y*3 + S;
2
X:= X div 3;
4
S:= T[S, X mod 3];
0
Y:= Y*3 + S;
6
X:= X div 3;
1
S:= T[S, X mod 3];
1
Y:= Y*3 + S;
19
X:= X div 3;
0
Ответ: 19
20
9-11 классы
21
Задача 1. Умножение (20 баллов)
Из имеющихся N целых чисел составить такую
тройку, произведение которой будет
максимальным.
Ограничение по времени: 2 сек.
Ограничение по памяти: 256 Мбайт
22
Формат входных данных
Первая строка входного файла содержит
число N – количество исходных чисел
(3 ≤ N ≤ 106). Во второй строке указаны
непосредственно сами числа – N чисел,
абсолютная величина которых не превышает
30 000.
Формат выходных данных
В выходной файл записать три искомых числа
в том порядке, в котором они расположены в
последовательности.
23
АНАЛИЗ
Если числа последовательности неотрицательные, то какие три её
числа дадут максимальное произведение?
1
7
3
10
6
5
4
12
1
Три максимальных числа последовательности max1, max2, max3.
А, если есть и отрицательные?
1
7
3
10
-6
5
4
-12
-1
Произведение 2-х отрицательных чисел положительно.
Поэтому, нужно найти и два минимальных числа min1 и min2.
Затем сравнить min1*min2 и max2*max3 и выбрать ту
пару, которая имеет наибольшее произведение.
Третье число к паре - max1
24
А, если все числа в последовательности отрицательные?
-1 -7 -3 -10 -6 -5 -4 -12 -1
Снова наибольшее произведение дадут три максимальных
числа max1, max2, max3.
25
Решение без учета порядка
program Z2014_1;
else
var n:longint;
if k>max2 then
max1,max2,max3,min1,min2,k,i:integer;
begin
f:text;
max3:=max2; max2:=k
begin
end
assign(f,'Task1.in');
else
reset(f);
if k>max3 then max3:=k;
max1:=-30000;
if k<min1 then
max2:=max1;
begin
max3:=max1;
min2:=min1; min1:=k
min1:=30000;
end
min2:=min1;
else
readln(f,n);
if k<min2 then min2:=k;
for i:=1 to n do
end;
begin
close(f);
read(f,k);
if (max1>0) and (min1*min2>max2*max3)
if k>max1 then
then
begin
write(f,max1,’ ‘,min1,’ ‘,min2)
max3:=max2; max2:=max1; max1:=k
else
end
write(f,max1,’ ‘,max2,’ ‘,max3);
end.
26
Решение с учетом порядка
program Z2014_1;
var n:longint;
a:array[0..1000001] of integer;
max1,max2,max3,min1,min2,i:integer;
f:text;
procedure print(x,y,z:integer);
procedure swap(var l,m:integer);
var t:integer;
begin
t:=l;
l:=m;
m:=t
end;
begin
if x>y then swap(x,y);
if x>z then swap(x,z);
if y>z then swap(y,z);
write(f,a[x],' ',a[y],' ',a[z])
end;
27
Решение с учетом порядка
begin
assign(f,'Task1.in');
reset(f);
readln(f,n);
a[0]:=-30001;
a[n+1]:=30001;
max1:=0;
max2:=0;
max3:=0;
min1:=n+1;
min2:=n+1;
for i:=1 to n do
begin
read(f,a[i]);
if a[i]>a[max1] then
begin
max3:=max2;
max2:=max1;
max1:=i
end
else
if a[i]>a[max2] then
begin
max3:=max2;
max2:=i
end
else
if a[i]>max3 then max3:=i;
if a[i]<a[min1] then
begin
min2:=min1;
min1:=i
end
else
if a[i]<a[min2] then min2:=i;
end;
close(f);
assign(f,'task1.out');
rewrite(f);
28
Решение с учетом порядка
if (a[max1]>0) and
(a[min1]*a[min2]>a[max2]*a[max3]) then
print(max1,min1,min2)
else
print(max1,max2,max3);
close(f)
end.
29
Задача 2. Гусеница. (30 баллов)
Гусеница может двигаться по ветке длины N только
вперед. Длина «шага» целое число не более K.
Сколько различных вариантов передвижения, при
которых гусеница пройдет по ветке от начала до
конца.
• Формат входных данных
• Первая строка файла содержит два целых числа N и
K, разделенных пробелом (1≤N≤15, 1≤K≤15, K≤N).
• Формат выходных данных
• Выходной файл содержит число различных
вариантов передвижения.
30
Задача из муниципального этапа 2011-2012
учебного года
Фишка. Фишка может двигаться только
вперед по полю длины N. Длина хода
фишки не может быть более K. Найти число
различных вариантов ходов, при которых
фишка может пройти поле от начала до
конца. Например, при N=3, K=2 –
возможные пути: (1,1,1), (1,2), (2,1), т.е.
возможны 3 варианта.
31
Решение
Динамическое программирование.
Прежде чем найти кол-во маршрутов до
позиции N, найдем кол-во маршрутов до
позиций 1, 2, 3, …, N-1).
0
1
2
3
…
N-1
N
Кол-во маршрутов будем хранить в
массиве S.
32
Сначала найдем позиции, в которые можно
дойти за 1 шаг. Очевидно, что это позиции
1, 2, 3, …, K. Занесем в S[1], S[2], …, S[K]
значения 1.
S:
1
1
1
0
1
2
3
…
1
0
…
K
…
…
N
33
В S[i] будем хранить количество маршрутов по
которым фишка может пройти поле от начала до
позиции с номером i.
В позицию i можно попасть из позиций i-1, i-2, …, i-K.
Каждый этот шаг это продолжение уже
существующего маршрута. Значит кол-во
маршрутов S[i] равно сумме S[i-1]+S[i-2]+…+S[i-K].
0
i-K
...
i-2
i-1
i
…
N
34
Таким образом, вычисляя последовательно значения
величин S[2], S[3],..., S[N] получаем значение S[N],
которое и указывает общее количество различных
путей, по которым фишка может пройти поле от
начала до позиции с номером N.
35
Решение 1
program O13_911_2;
var n,k,i,j:integer;
s:array[1..10] of integer;
begin
assign(input,'task2.txt'); reset(input); readln(n,k); close(input);
assign(output,'task2.out'); rewrite(output);
for i:=1 to n do
if i<=k then s[i]:=1 else s[i]:=0;
for i:=2 to n do
begin
j:=i-1;
while (j>0) and (j>=i-k) do
begin
s[i]:=s[i]+s[j];
j:=j-1
end
end;
write(s[n]);
close(output)
end.
36
Решение 2
Рассмотрим процесс заполнения таблицы S при N=6, K=3
1
1
1
0
0
0
i=2
1
2
1
0
0
0
2=2*1-0
i=3
1
2
4
0
0
0
4=2*2-0
i=4
1
2
4
7
0
0
7=2*4-1
i=5
1
2
4
7
13
0
13=2*7-1
i=6
1
2
4
7
13
24
24=2*13-2
a[i]=2*a[i-1] – a[i-k-1]
37
Решение 2
var a:array[-16..15] of integer;
i,n,k:integer; f:text;
begin
assign(f,'task2.in');
reset(f);}
read(n,k);
close(f);
assign(f,'task2.out');
rewrite(f);
for i:=-16 to -1 do a[i]:=0;
a[0]:=1;
a[1]:=1;
for i:=2 to n do
a[i]:=2*a[i-1]-a[i-k-1];
writeln(f,a[n]);
close(f)
end.
38
Задача 3. Водопровод. (50 баллов)
• . В Кибер-городке построили новый
водопровод, который представляет из себя
связную фигуру, состоящую из труб. Схема
водопровода показа на рисунке, согласно
которому видно, что сама схема привязана
к прямоугольной системе координат XOY.
Конструкция водопровода имеет
следующие особенности:
39
• трубы первого типа имеют длину 1 и выкладываются
параллельно осям координат (таким образом, что их
начало и конец имеют целочисленные координаты);
• трубы второго типа имеют длину и выкладываются
под углом 45 градусов по отношению к осям координат.
Их начало и конец также имеют целочисленные
координаты;
• в местах каждого сопряжения труб имеется свой кран внешнего
подключения, позволяющий наполнить весь водопровод водой;
• каждая труба имеет свою скорость наполнения водой;
• пересечение труб типа 2 в нецелочисленной координате означает, что
эти трубы также сопряжены и в этой точке, т.е. вода, достигнув этой
точки, начинает распространяться уже в направлении двух труб.
40
Перед сдачей водопровода в эксплуатацию его необходимо
полностью заполнить водой (предполагается, что изначально
водопровод абсолютно пуст). При этом заполнить его возможно,
используя только один из имеющихся кранов внешнего
подключения. Напоминаем, что кран внешнего подключения это
точка с целочисленными координатами (например, в точке А на
рисунке подключение к водопроводу для заполнения
невозможно, а в точках В и С – можно).
Известно, что вода распространяется вдоль труб равномерно (но
по каждой трубе – со своей скоростью). Труба может наполняться
в нескольких местах (например, когда она заполняется с двух
концов; или когда в середине диагональной трубы вода попадает
из одной трубы в другую – вода распространяется по вновь
заполняемой трубе в обе стороны).
Написать программу, которая вычислит целочисленные
координаты точки, подключение к которой позволит заполнить
весь водопровод за минимальное время.
41
Формат входных данных.
Первая строка входного файла содержит число N – количество
труб (1≤N≤40). Затем идут N пятерок чисел вида Х1, Y1, Х2, Y2, T,
задающих координаты концов трубы и время ее наполнения при
условии, что она будет заполняться с одного конца (гарантируется,
что каждая труба имеет длину 1 или , все трубы образуют связную
фигуру и положение никаких двух труб не совпадает). Все
координаты – целые числа, по модулю не превышающие 200, а
время наполнения – натуральное число, не превышающее 107.
Формат выходных данных.
В первую строку выходного файла вывести координаты
целочисленной точки, в которой нужно подключиться к
водопроводу, чтобы он наполнился за наименьшее время. Во
второй строке вывести соответствующее время, за которое в этом
случае заполнится водопровод. Время должно быть выведено с
точностью не менее 2 знаков после десятичной точки. Если
решений несколько, вывести любое из них.
42
Решение. Алгоритм Флойда
Алгоритм Флойда является одним из методов поиска кратчайших путей в графе.
Прежде чем представлять алгоритм, необходимо ввести
некоторые обозначения.
Перенумеруем вершины исходного графа целыми числами от 1
до N. Обозначим через
m
d i, j
длину кратчайшего
пути из
вершины i в вершину j, который в качестве промежуточных
может содержать только первые m вершин графа.
(Промежуточной вершиной пути является любая
принадлежащая ему вершина, не совпадающая с его
начальной или конечной
вершинами.)
43
Если между вершинами i и j не существует ни одного пути
d i , j . 
m
указанного типа, то условно будем считать, что
m
d
Из данного определения величин
следует,
что величина
i, j
0
d i , j представляет длину кратчайшего пути из вершины i в
вершину j, не имеющего промежуточных вершин, т. е. длину
кратчайшей дуги, соединяющей i с j (если такие дуги
присутствуют в графе). Для любой вершины i положим
Отметим далее, что величина
d i ,i  0
m
m
d iпредставляет
длину
,j
кратчайшего пути между вершинами i и j.
44
Обозначим через D mматрицу размера NxN, элемент (i, j)
которой совпадает с
m
d i , .j Если в исходном графе нам известна
длина каждой дуги, то мы можем сформировать матрицу
0
Наша цельDсостоит
в определении матрицы
,
.
D
N
представляющей кратчайшие пути между всеми вершинами
рассматриваемого графа.
45
В алгоритме Флойда в качестве исходной выступает матрица
0
Вначале из
D этой матрицы вычисляется матрица
матрице D 1 вычисляется матрицаD 1
повторяется до тех пор, пока по матрице
вычислена матрица
.
D
.
. Затем по
и т. д. Процесс
не будет
D
D
2
N 1
N
46
Рассмотрим основную идею, лежащую в основе
алгоритма Флойда. Суть алгоритма Флойда заключается
в проверке того, не окажется ли путь из вершины i в
вершину j короче, если он будет проходить через
некоторую промежуточную вершину m.
47
Предположим, что нам известны:
1. Кратчайший путь из вершины i в вершину m, в котором в
качестве промежуточных допускается использование
только первых (m - 1) вершин;
2. Кратчайший путь из вершины m в вершину j, в котором в
качестве промежуточных допускается использование
только первых (m - 1) вершин;
3. кратчайший путь из вершины i в вершину j, в котором в
качестве промежуточных допускается использование
только первых (m - 1) вершин.
48
Тогда, один из двух путей — путь, совпадающий с
представленным в пункте 3, или путь, являющийся
объединением путей из пунктов 1 и 2 — должен быть
кратчайшим путем из вершины i в вершину j, в котором в
качестве промежуточных допускается использование только
первых m вершин. Таким образом,
d i , j  m in  d i , m  d m , j ; d i , j
m
m 1
m 1
m 1

49
Решение задачи.
Прежде всего заметим, что трубы могут пересекаться только
концами либо серединами. Других случаев пересечения быть
не может. Таким образом, если разбить каждую трубу на две
«половинки» вдвое меньшей длины, то полученные
«полутрубы» пересекаться будут только концами. Если все
координаты исходных труб умножить на два, то координаты
всех «полутруб» также будут выражаться целыми числами.
Далее, если на два умножить также и время заполнения всех
труб, то время заполнения «полутрубы» также будет
выражаться целым числом секунд. Будем считать, что мы так
уже поступили, и далее трубами именуются именно такие
«полутрубы».
50
Мы перешли к аналогичной задаче с вдвое большим
количеством труб с целыми координатами, пересекающихся
только концами. Построим граф, ребрами которого будут
трубы, а вершинами — их концы. Задача сводится к
нахождению такой вершины графа, при подключении к
которой весь граф «заполняется» за минимальное время.
Будем решать задачу перебором по всем потенциальным
«точкам подключения». Так как в любом случае необходимо
в выходной файл вывести кроме координат оптимальной
точки общее время наполнения, задачу о нахождении
времени «наполнения» графа при подключении данной
вершины тоже надо уметь решать.
51
Пусть нам дан граф, в котором на каждом ребре записано
время наполнения соответствующей ему трубы (эту величину
будем называть весом или длиной ребра), и в нем
зафиксирована некоторая вершина. Как найти время
«наполнения» этого графа при подключении этой вершины?
Ясно, что время «наполнения» графа равно расстоянию от
зафиксированной вершины до наиболее удаленной от нее
точки графа. Именно «наиболее удаленной точки», а не
«наиболее удаленной вершины»! Простейший пример, где
эти понятия различаются — треугольник.
52
Допустим, в приведенном выше примере время наполнения
вертикальной и диагональной трубы — одна секунда, а
время наполнения горизонтальной трубы— четыре секунды.
Тогда при подключении этой фигуры в верхней точке через
секунду вода достигнет обоих концов основания.
Еще две секунды потребуется воде, чтобы
заполнить основание. Таким образом, хотя самая
удаленная вершина находится на расстоянии 1 от точки
подключения, суммарное время наполнения
такой фигуры равно трем секундам.
53
Вычислим кратчайшие расстояния от данной вершины до
всех остальных. Кратчайшее расстояние соответствует
моменту времени, когда вода достигнет данной вершины.
Для нахождения расстояний и будем использовать алгоритм
Флойда.
for k:=1 to N do
for i:=1 to N do
for j:=1 to N do
if a[i, j]<a[i,k] +a[k, j] then a[i, j] : =a[i,k]+a[k, j] ;
54
После нахождения кратчайших путей из «подключаемой»
вершины во все остальные, нам известно время, за которое
вода достигнет каждой из вершин. Теперь нужно проверить
все ребра-трубы на предмет того, наполнились ли они уже в
процессе перемещения воды до вершин, а если нет, то
нужно найти время, когда наполнится данная труба.
Максимальное из этих времен даст ответ.
Пусть вода достигает концов трубы со временем наполнения
L в моменты времени Т1 и Т2. Если Т1 = Т2 + L или Т2 = Т1 + L,
то вода протекала по этой трубе и максимум из Т1 и Т2 и
будет тем временем, к которому труба наполнится
полностью.
55
Пусть теперь разность между Т1 и Т2 не равна L. Это значит,
что к разным концам трубы вода подошла разными путями,
она будет заполняться одновременно с обеих сторон.
Напомним, что под трубой мы понимаем половину трубы, и
пересекаться не в концах она уже ни с чем не может. Значит
начать заполнять такая труба никакую другую трубу не может
— с обоих ее концов уже и так идет заполнение! В
простейшем случае, если труба заполняется одновременно с
обоих концов, она наполнится за время L/2. Трудность в том,
что в общем случае время начала заполнения концов трубы
может не совпадать.
56
Можно вычесть одно и то же число из Т1 и из Т2, т. е. мы
можем перейти к задаче, где один конец начинает
заполняться в момент времени 0, а второй — в момент
времени Т. Общее время наполнения трубы в таком случае
будет равно Т + (L — Т)/2. Прийти к этой формуле проще
всего исходя из следующих соображений. Пусть труба имеет
длину L метров и наполняется со скоростью 1 метр в секунду.
Тогда первые Т секунд она будет наполняться с одного конца
и наполнится на Т метров, а оставшееся время потребуется
на то, чтобы наполнить L — Т метров со скоростью 2 м/сек, т.
е. время наполнения этого фрагмента трубы будет равно (L
— Т)/2. При Т = 0 формула дает ответ L/2, а при Т = L —
ответ L, что полностью согласуется с условием задачи.
57
Мы теперь умеем решать задачу о нахождении времени
наполнения данной конфигурации труб при ее подключении
в данной точке. Для этого нужно в соответствующем данной
конфигурации графе найти максимум из времен заполнений
каждого из ребер. И не забыть разделить его пополам —
ведь при построении графа мы удвоили время наполнения
каждой трубы.
Теперь мы можем решить задачу перебором по вершинам.
Проверив все потенциальные точки подключения и выбрав
из них ту, при подключении которой время наполнения
минимально, мы найдем ответ.
58
Необходимо учесть, что не каждая из вершин достроенного
графа может быть точкой подключения. Так как мы
раздвоили каждую трубу, в наш граф войдут также вершины,
соответствующие серединам труб. Из всех точек мы должны
выбрать те, координаты которых нацело делятся на два.
59
Program O2013_Z3;
Const
MaxN=42; { Ограничение на N }
MaxG=2*MaxN+1; { Ограничение на число вершин в графе }
Infinity=2147483647; { "Бесконечное" расстояние }
Var
N:Integer;
F:Text;
Match:Array[1..MaxN]Of Record { Входные }
X1,Y1,X2,Y2:Integer;
{ данные }
Time:LongInt;
End;
NG:Integer;
{
}
Vertex:Array[1..MaxG]Of Record {
}
X,Y:Integer;
{ Граф }
End;
{
}
Edge,Distance:Array[1..MaxG,1..MaxG]Of LongInt;
Res:Real;
{ Минимальное время наполнения }
ResX,ResY:Integer; { Оптимальная точка подключения }
60
Procedure Load;
Var
I:Integer;
Begin
Assign(F,'Task3.In');
ReSet(F);
Read(F,N);
For I:=1 To N Do
With Match[I] Do
Read(F,X1,Y1,X2,Y2,Time);
Close(F);
End;
61
Function GetVertex(VX,VY:Integer):Integer;
{ Функция, возвращающая номер вершины с заданными координатами.
При отсутствии нужной вершины она создаётся }
Var I:Integer;
Begin
For I:=1 To NG Do
With Vertex[I] Do
If (X=VX) And (Y=VY) Then Begin
GetVertex:=I;
Exit;
End;
Inc(NG); { Если нужная вершина не найдена }
With Vertex[NG] Do Begin
X:=VX; Y:=VY;
For I:=1 To NG-1 Do Begin
Edge[I,NG]:=Infinity;
Edge[NG,I]:=Infinity;
End;
Edge[NG,NG]:=0;
End;
GetVertex:=NG;
End;
62
Procedure AddEdge(X1,Y1,X2,Y2:Integer; Time:Longint);
{ Функция, добавляющая ребро между двумя точками }
Var
A,B:Integer;
Begin
A:=GetVertex(X1,Y1);
B:=GetVertex(X2,Y2);
Edge[A,B]:=Time;
Edge[B,A]:=Time;
End;
Procedure BuildGraph; { Процедура построения графа }
Var
I:Integer;
Begin
NG:=0;
For I:=1 To N Do
With Match[I] Do Begin
AddEdge(X1*2,Y1*2,X1+X2,Y1+Y2,Time);
AddEdge(X1+X2,Y1+Y2,X2*2,Y2*2,Time);
End;
End;
63
Procedure FindShortestPaths;
Var
K,I,J:Integer;
Begin
Distance:=Edge;
For K:=1 To NG Do
For I:=1 To NG Do If Distance[I,K]<Infinity Then
For J:=1 To NG Do If Distance[K,J]<Infinity Then
If Distance[I,K]+Distance[K,J]<Distance[I,J] Then
Distance[I,J]:=Distance[I,K]+Distance[K,J];
End;
64
Function BurnAt(At:Integer):Extended;
{ Функция, вычисляющая время наполнения при подключении в точке At }
Var
I,J:Integer;
Cur,ThisEdge:Real;
Begin
Cur:=0;
For I:=1 To NG Do If Distance[At,I]>Cur Then Cur:=Distance[At,I];
For I:=1 To NG Do
For J:=I+1 To NG Do If Edge[I,J]<Infinity Then Begin
If (Distance[At,I]<Distance[At,J]+Edge[I,J]) And
(Distance[At,J]<Distance[At,I]+Edge[I,J]) Then Begin
If Distance[At,I]<Distance[At,J] Then
ThisEdge:=Distance[At,J]+(Edge[I,J]-(Distance[At,J]-Distance[At,I]))/2
Else
ThisEdge:=Distance[At,I]+(Edge[I,J]-(Distance[At,I]-Distance[At,J]))/2;
If ThisEdge>Cur Then Cur:=ThisEdge;
End;
End;
BurnAt:=Cur;
End;
65
Procedure Solve;
Var
I:Integer;
Cur:Real;
Begin
Res:=Infinity;
For I:=1 To NG Do
With Vertex[I] Do
If Not Odd(X) And Not Odd(Y) Then Begin
Cur:=BurnAt(I);
If Cur<Res Then Begin
Res:=Cur;
ResX:=X Div 2;
ResY:=Y Div 2;
End;
End;
End;
66
Procedure Save;
Begin
Assign(F,’Task3.Out’);
ReWrite(F);
WriteLn(F,ResX,' ',ResY);
WriteLn(F,Res/2:0:2);
Close(F);
End;
Begin
Load;
BuildGraph;
FindShortestPaths;
Solve;
Save;
End.
67