На форумі обговорюються лише питання, пов'язані з олімпіадою
Ви не зайшли.
Итак 4-й тур прошел!
Жюри очень хорошо потрудилось над условиями, задачи были уровня всеукраинских, а то и международных олимпиад и достаточно нестандартные, что не может не радовать. Поэтому выражаю свое впечатление о задачах:
SUBNET:
Задача очень оригинальная, мне понравилась. Как оказалось, основная проблема - это понять условие
Самое хорошее решение: запускаем Дейкстру из сервера. Потом возвращаемся из всех К вершин рекурсией назад помечая дуги, по которым идет хотя бы один оптимальный путь для каждой из К вершин. Потом смотрим какие дуги оказались помечены для всех К компьютеров. Получаем, что в графе есть некоторые помеченые дуги, причем можно доказать, что эти дуги образуют дерево. Высота этого дерева и будет ответом. Такое решение набирало 100 балов (например, так сделал Батыев Андрей).
Я реализовал более тупое решение, которое впрочем набрало 95 балов
Запускаем из каждой из К вершин по Дейкстре. Потом рекурсивно идем и сервера обходом в глубину и для каждой вершины в этом обходе проверяем равняется ли длина оптимального пути ко всем К вершинам из нее плюс длина пути к этой вершине длине оптимального пути для каждой из К вершин (во завернул!)
Короче говоря, вот мое решение (95 балов - 1 TimeLimit)
type
TArr = array [1..1000] of Longint;
var
N, M, K, i, j, l, x,y,z : integer;
F : array [1..1000] of Integer;
V : array [1..20000] of record
e,l,next : Integer;
end;
B : array [1..100] of Integer;
D : array [0..100] of TArr;
Q : array [1..1000] of Boolean;
ans : Integer;
procedure pr(st : Integer; var M : TArr);
var
i,j,min,w,t : Integer;
begin
FillChar(Q, SizeOf(Q), 0);
for i := 1 to N do
M[i] := maxlongint;
M[st] := 0;
for j := 1 to N do
begin
min := -1;
for i := 1 to N do
if not Q[i] and ((min = -1) or (M[min] > M[i])) then
min := i;
if min = -1 then
Break;
Q[min] := True;
w := F[min];
while w <> 0 do
begin
if not Q[V[w].e] then
begin
t := M[min]+V[w].l;
if t < M[V[w].e] then
M[V[w].e] := t;
end;
w := V[w].next;
end;
end;
end;
procedure Rec(ver, step, len : longint);
var
w, i, j, vv : Integer;
ok : Boolean;
begin
if len > ans then
ans := len;
Q[ver] := True;
w := F[ver];
while w <> 0 do
begin
vv := V[w].e;
if not Q[vv] then
begin
ok := True;
for i := 1 to K do
if D[i][1] <> D[i][vv]+len+V[w].l then
begin
ok := False;
Break;
end;
if ok then
rec(vv, step+1, len+V[w].l);
end;
w := V[w].next;
end;
Q[ver] := False;
end;
begin
Read(N,M,K);
for i := 1 to K do
Read(B[i]);
for i := 1 to M do
begin
Read(x,y,z);
V[i*2-1].e := y;
V[i*2-1].l := z;
V[i*2-1].next := F[x];
F[x] := i*2-1;
V[i*2].e := x;
V[i*2].l := z;
V[i*2].next := F[y];
F[y] := i*2;
end;
Pr(1, D[0]);
for i := 1 to K do
Pr(B[i], D[i]);
FillChar(Q, SizeOf(Q), 0);
ans := -1;
Rec(1, 0, 0);
WriteLn(ans);
end.NEWSUBNET:
Как оказалось, это вообще "фонарь"! Правильное решение - найти максимальное расстояние между двумя передающими компьютерами и разделить его пополам!!! Я естественно до этого не додумался и послал полный перебор, который набрал 1 балл!!! Правильное решение до смешного простое:
var
N, i, j, max, t : Integer;
A : array [1..1000] of record x,y : Integer; end;
begin
Read(N);
for i := 1 to N do
Read(A[i].x, A[i].y);
max := 0;
for i := 1 to N do
for j := i+1 to N do
begin
t := Abs(A[i].x-A[j].x)+Abs(A[i].y-A[j].y);
if t > max then max := t;
end;
WriteLn((max+1) div 2);
end.JUMP
Без комментариев! Физика, математика и много технического программирования. Я ей не очень занимался и набрал всего 13 балов. Лучший результат у Шамова Александра - 48 баллов (за исключением Жюри, конечно). Решение даже не публикую изза его отсутствия.
SPACE
Лобовое решение, в котором нужно не пропустить несколько тонких моментов с организацией очереди. Думаю, что написать рабочее решение не составит труда. У меня небольшой глюк, изза которого я получил всего 84.
FOUR
Чесно говоря, мне эта задача страшно понравилась! Первое, что приходит в голову - жадный алгоритм. Но он тут не работает!!! Насколько я знаю, все кто написал его ("пожадничал" так сказать) получили не больше 55 балов. Я сделал динамику, хотя объяснить как она работает до сих пор не могу
Но результат за задачу 100 баллов:
var
N,t,i,K,j,x,v,m : Integer;
A : array [1..100] of Integer;
G, GG : array [0..1000] of Word;
maxG, maxGG : Integer;
procedure check(x, v : Integer);
begin
if G[x] > v then
begin
G[x] := v;
if x > maxG then
maxG := x;
end;
end;
begin
Read(N);
FillChar(A, SizeOf(A), 0);
for i := 1 to N do
begin
Read(t);
Inc(A[t]);
end;
N := 0;
FillChar(GG, SizeOf(GG), $FF);
maxGG := 0;
GG[0] := 0;
for i := 1 to 100 do
if A[i] <> 0 then
begin
FillChar(G, SizeOf(G), $FF);
maxG := 0;
t := (4-A[i] mod 4)mod 4;
m := A[i] mod 4;
for j := 0 to maxGG do
if GG[j] <> $FFFF then
begin
Check(j+t, GG[j]);
x := j-m;
v := GG[j]+m;
if x >= 0 then
for k := A[i] div 4 downto 0 do
begin
Check(x,v);
Dec(x,4);
Inc(v, 4);
if x < 0 then
Break;
end;
end;
GG := G;
maxGG := maxG;
end;
WriteLn(GG[0]);
end.Итого у меня 293 балла. Вроде прохожу на Всеукраинскую.
В целом олимпиада очень понравилась, жюри потрудилось на славу! Так держать!
Поза форумом
А теперь прикол: решение задачи NewSubnet неправильное :-)
К нему есть контрпример :-)
Поза форумом
До журі:
Розвязок задачі NewSubnet , який шукає найдовший шлях між двома точками, ділить навпіл і виводить як результат проходить всі тести. Але наприклад у тесті 4 1 4 1 5 7 1 9 6 замість відповіді 5 (по цьому алгоритму) мусить бути відповідь 6. Тобто тести правильні, просто неправильний розвязок проходить як і правильний всі тести.
Поза форумом
Тут я вижу меня вспомнили...
И так SUBNET
program subnet;
const maxn=1000;
maxk=100;
infinity=1000000000;
var g:array[1..maxn,1..maxn]of longint;
d:array[1..maxn]of longint;
sel:array[1..maxk]of longint;
us:array[1..maxn]of boolean;
sel_us:array[1..maxk,1..maxn]of boolean;
n,m,k,res:longint;
procedure Init;
var i,p,q,l:longint;
begin
read(n,m,k);
for i:=1 to k do
begin
read(sel[i]);
for p:=1 to n do
sel_us[i,p]:=false;
end;
for p:=1 to n do
begin
for q:=1 to n do
g[p,q]:=infinity;
d[p]:=infinity;
us[p]:=false;
end;
d[1]:=0;
for i:=1 to m do
begin
read(p,q,l);
g[p,q]:=l;
g[q,p]:=l;
end;
end;
procedure Relax(u,v:longint);
begin
if d[v]>d[u]+g[u,v] then
d[v]:=d[u]+g[u,v];
end;
procedure recurse_ways(t,p:longint);
var i:longint;
begin
if not sel_us[t,p] then
begin
sel_us[t,p]:=true;
for i:=1 to n do
if d[i]+g[i,p]=d[p] then
recurse_ways(t,i);
end;
end;
procedure ScanForResult;
var i,j:longint;
p:boolean;
begin
res:=0;
for i:=1 to n do
begin
p:=true;
for j:=1 to k do
begin
p:=p and sel_us[j,i];
if not p then
break;
end;
if p and (res<d[i]) then
res:=d[i];
end;
end;
procedure Solve;
var now,i,j,t,min:longint;
begin
now:=1;
for i:=1 to n-1 do
begin
us[now]:=true; min:=infinity;
for j:=1 to n do
if not us[j] then
begin
Relax(now,j);
if min>d[j] then
begin
t:=j;
min:=d[j];
end;
end;
now:=t;
end;
for i:=1 to k do
recurse_ways(i,sel[i]);
ScanForResult;
end;
procedure WriteResult;
begin
writeln(res);
end;
begin
Init;
Solve;
WriteResult;
end.Поза форумом
Трегубенко Антон написав:
До журі:
Розвязок задачі NewSubnet , який шукає найдовший шлях між двома точками, ділить навпіл і виводить як результат проходить всі тести. Але наприклад у тесті 4 1 4 1 5 7 1 9 6 замість відповіді 5 (по цьому алгоритму) мусить бути відповідь 6. Тобто тести правильні, просто неправильний розвязок проходить як і правильний всі тести.
Ваш пример некорректен. Возможно, вы что-то пропустили?
Ведь в задаче.....
Технічні умови: Програма читає з клавіатури цілі числа N, M, K, далі - K натуральних чисел, далі - M груп по три натуральних числа -номери з'єднаних комп'ютерів та довжина каналу між ними, що не перевищує 1000. Всі числа розділено пропусками. Мережу збудовано так, що пакети з будь-якого комп'ютера можуть дістатися до сервера.
(2<=N<=1000, 1<=M<=10000, 1<=K<=100)
N - кількість комп'ютерівв мережі,
M - кількість відрізків кабелю, що з'єднують комп'ютери попарно,
К -кількість комп'ютерів, що надсилають сигнали на сервер (введені К натуральних чисел - їх номери).
Програма виводить на екран найбільшу довжину каналів, якими, за згаданих умов, проходять пакети від всіх К комп'ютерів на сервер.
Приведите правильный тест в защиту ваших аргументов.
Поза форумом
По-моєму ви поплутали Subnet з NewSubNet
Вобще, контрприклад вірний. ![]()
Поза форумом
Vladislav Simonenko написав:
По-моєму ви поплутали Subnet з NewSubNet
![]()
Вобще, контрприклад вірний.
Дійсно, і задачі переплутав ( три доби неперервної роботи) :-(, і контрприклад правильний. Публікую авторський розв'язок
program NewSubNet;
{Pupkin}
const
S=2000;
MaxN=1000;
type
koor = record
x, y : integer
end;
var
koords : array[1..MaxN] of koor;
i, j, k, N : integer;
bestr, maxl, r : integer;
best : koor;
x,y,xpy,xmy,x0y0,x0y1,x1y0,x1y1,x0y0g,x0y1g,x1y0g,x1y1g,rp,rn,maxr : integer;
begin
Read(N);
for k:=1 to N do Read(koords[k].x,koords[k].y);
x0y0 := S+S+1; x1y1 := 0; x0y1 := S+S+1; x1y0 := -S-1;
for k := 1 to N do begin
xpy := koords[k].x + koords[k].y;
xmy := koords[k].x - koords[k].y;
if xpy < x0y0 then x0y0 := xpy;
if xpy > x1y1 then x1y1 := xpy;
if xmy < x0y1 then x0y1 := xmy;
if xmy > x1y0 then x1y0 := xmy;
end;
rp := x1y1 - x0y0; rn := x1y0 - x0y1;
if rp > rn then r := rp else r := rn;
maxr := (r div 2) + 1;
x0y0g := x0y0+maxr; x1y1g := x1y1-maxr; x0y1g := x0y1+maxr; x1y0g := x1y0-maxr;
bestr := S;
for i:=x1y1g to x0y0g do begin
j:=x1y0g;
x := (i+j+1) div 2; y := i-x;
while x-y < x0y1g do begin
maxl := 0;
for k:=1 to N do begin
r := abs(koords[k].x-x)+abs(koords[k].y-y);
if r > maxl then maxl := r;
end;
if maxl < bestr then begin
bestr := maxl;
best.x := x;
best.y := y;
end;
inc(x); dec(y);
end
end;
Write({best.x,' ',best.y,' '}bestr);
end.
--------------
Він проходить цей тест. На жаль, жодна з 100 - бальних робіт учасників його не пройшла. Автору задачі не вдалося придумати таку "евристику", яку придумало досить немало учасників, тому й не було такого теста....Але всі тести, що використовувалися при перевірці, правильні.
Запропонований тест включено до набору тестів, проведена повторна перевірка. Результати можна побачити на сторінці 4-го туру. Розполділ місць не змінився, хоча ситуація, що склалася, не прикрашає журі.
Поза форумом
Может быть справедливо было бы для задачи NewSubNet добавить несколько тестов, подобных предложеному Трегубенко Антоном. Ведь в других задачах неправильный алгоритм не давал и 60% баллов.
Поза форумом
Дуже дякую за включення тесту. Завдяки цьому я опинився на 3-ому місці 4-ого туру олімпіади.
Журі NetOI-2005 - Пасіхов написав:
На жаль, жодна з 100 - бальних робіт учасників його не пройшла.
У мене залишилося 100 балів. Як ви помітите - у інших балли знизилися. Я теж вважаю що справедливим було б додати більше подібних тестів.
Мені жаль, що у Симоненка Владислава (100-5) баллів за другу задачу, бо якщо б він отримав менше 50 баллів за неправильний розвязок, то я би опинився на другому місці після Джулгакова
.
Все одно дякую за включення цього тесту.
Відредаговано Трегубенко Антон (2006-02-05 22:36:29)
Поза форумом
Поддерживаю Трегубенко Антона и Ivana по поводу newsubnet:
тест: 3 1 1 9 1 5 9
ответ: 6 (пакеты встречаются в точке (5;3))
другой алгоритм, если я не ошибаюсь, дает ответ 8
Відредаговано Nicky Nick (2006-02-05 22:48:16)
Поза форумом
Дійсно , тест цікавий. Вобще, я писав спочатку розв’язок за O(n^2), він точно вірний, але потім випадково прийшла ідея перевірити дану евристику, виявилося, що вона така сама квадратна , але константа при О набагато менша. Ну згенерував 40 тестів випадковим, і виявилося що відповіді повністю співпадають !!! Такий тест реально складно було знайти(особисто для мене) ... Ну я й зробив помилку ... Але от це :
У мене залишилося 100 балів. Як ви помітите - у інших балли знизилися. Я теж вважаю що справедливим було б додати більше подібних тестів.
Мені жаль, що у Симоненка Владислава (100-5) баллів за другу задачу, бо якщо б він отримав менше 50 баллів за неправильний розвязок, то я би опинився на другому місці після Джулгакова.
Все одно дякую за включення цього тесту.
lol... Ну якщо так думати , то і Джулгакову треба було б ще побільше тестів дати на першу задачу, подібних до тесту який у нього вона не пройшла. Було б у нього не (100-5) балів , а менше 50 баллів. Ти був би не другий... А перший перед Джулгаковим... Робота журі не заключається у здійснені плану 1062 задачі Тімуса:)
Відредаговано Vladislav Simonenko (2006-02-05 23:42:39)
Поза форумом
Просьба к жюри:
Так как до сих пор судейство NetOI отличалось своей справедливостью и прозрачностью, было бы справдливо кардинально пересмотреть набор тестов (распределение баллов) по задаче NewSubNet так, чтобы правильное (но неэффективное) решение не набирало на 90 (!) баллов меньше, чем не правильное (случайно совпавшее с ответом).
Поза форумом
Alexey написав:
Просьба к жюри:
Так как до сих пор судейство NetOI отличалось своей справедливостью и прозрачностью, было бы справдливо кардинально пересмотреть набор тестов (распределение баллов) по задаче NewSubNet так, чтобы правильное (но неэффективное) решение не набирало на 90 (!) баллов меньше, чем не правильное (случайно совпавшее с ответом).
Есть предложение закрыть тему.
1. Я благодарен за комплимент в адрес работы жюри.
2. К сожалению, ситуация с данной задачей жюри не украшает. (подобная эвристика в упор не приходила на ум, хотя лежит на поверхности ![]()
3. 300 (!) случайных тестов, згегирированих мною, она прошла без проблем, т.е. получить случайный тест, ее "заганяющий", мне не удалось.
4. Мы добавили предложеный тест в набор, произвели перепроверку.
5. Тон дискуссии мне не нравится.
6. Олимпиада закончена. Поздравляем победителей.
Поза форумом
Журі NetOI-2005 - Пасіхов написав:
5. Тон дискуссии мне не нравится.
Не понял упрёка. Я старался быть корректным. Просто пытался отстоять свою точку зрения. Но если проявил но отношению к кому-то некорректность, прошу извинть.
Поза форумом
До Vladislav Simonenko
У мене складність алгоритму O(n) . 100 балів. Доведено математично правильність алгоритму.
Поза форумом
Alexey написав:
Журі NetOI-2005 - Пасіхов написав:
5. Тон дискуссии мне не нравится.
Не понял упрёка. Я старался быть корректным. Просто пытался отстоять свою точку зрения. Но если проявил но отношению к кому-то некорректность, прошу извинть.
Почему вы решили что упрек в ваш адрес? Отнюдь. Мне не нравится выяснения отношений между участниками в смысле "кто больший гуру". Но и это не упрек. Мне просто не нравится. Да и расстроен слегка. Эвристика-то очевидная....("Хорошо быть умным, как моя жена потом"...есть такая старинная еврейская поговорка...)
Поза форумом
Трегубенко Антон написав:
До Vladislav Simonenko
У мене складність алгоритму O(n) . 100 балів. Доведено математично правильність алгоритму.
Журі буде вдечне, якщо ви опублікуєте свлї міркування.Наш розв'язок опубліковано. Кращого не маємо.
Поза форумом
Трегубенко Антон написав:
До Vladislav Simonenko
У мене складність алгоритму O(n) . 100 балів. Доведено математично правильність алгоритму.
Я ж не проти. Я не писав що такого алгоритму не існує
, просто написав як я робив цю задачу. Короче, ладно, мабуть дискусію треба завершувати... Поздоровляю , тепер вже напевно зустрінемось на всеукрі... Удачі !!!
Поза форумом
Журі NetOI-2005 - Пасіхов написав:
Да и расстроен слегка. Эвристика-то очевидная....("Хорошо быть умным, как моя жена потом"...есть такая старинная еврейская поговорка...)
Не ошибается тот, кто ничего не делает...
Олимпиада в целом очень качественно подготовлена (есть с чем сравнить), интересная и нужная. Так что расстраиваться нет причин :-)
Поза форумом
Журі NetOI-2005 - Пасіхов написав:
Трегубенко Антон написав:
До Vladislav Simonenko
У мене складність алгоритму O(n) . 100 балів. Доведено математично правильність алгоритму.Журі буде вдечне, якщо ви опублікуєте свлї міркування.Наш розв'язок опубліковано. Кращого не маємо.
Мій алгоритм схожий на ваш першою половиною. Ідея розвязання - якщо пакети дійдуть до точки А(х0;у0) за час Т , то ГМТ точок віддалених від А не більше ніж на Т (по вузлам, як біжать пакети) буде ромбом.
program NewSubNet;
Const MaxN = 2000;
type MTPoint = record
x:integer;
y:integer;
end;
var n,i:integer;
Points:array[1..MaxN] of MTPoint;
LeftTopPoint,RightTopPoint,LeftBottomPoint,RightBottomPoint:integer;
Distance1,Distance2:integer;
T:integer;
function Max(a,b:integer):integer;
begin
Max:=(a+b+abs(a-b)) div 2;
end;
begin
read(n);
for i:=1 to n do
read(Points[i].x,Points[i].y);
{Найменший ромб з діагоналями паралельними осям координат, який покриває всі точки}
{Знаходимо ліву верхню, праву верхню, ліву нижню і праву нижню точки}
LeftTopPoint:=1;
RightTopPoint:=1;
LeftBottomPoint:=1;
RightBottomPoint:=1;
for i:=2 to n do
begin
if Points[i].x + Points[i].y < Points[LeftTopPoint].x + Points[LeftTopPoint].y then
LeftTopPoint:=i;
if Points[i].x + Points[i].y > Points[RightBottomPoint].x + Points[RightBottomPoint].y then
RightBottomPoint:=i;
if Points[i].x - Points[i].y < Points[LeftBottomPoint].x + Points[LeftBottomPoint].y then
LeftBottomPoint:=i;
if Points[i].x - Points[i].y > Points[RightTopPoint].x + Points[RightTopPoint].y then
RightTopPoint:=i;
end;
{Подвоєна відстань між лівою верхньою та правою нижньою точками. Відстань рахується по довжині частини прямої у=0 (або х=0, всеодно), яка лежить між прямими у=х+с, які проходять через данні точки}
Distance1:=(Points[RightBottomPoint].x + Points[RightBottomPoint].y) - (Points[LeftTopPoint].x + Points[LeftTopPoint].y);
{Подвоєна відстань між лівою нижньою та правою верхньою точками}
Distance2:=(Points[RightTopPoint].x - Points[RightTopPoint].y) - (Points[LeftBottomPoint].x - Points[LeftBottomPoint].y);
{Шукане Т буде більше за ці відстані. С геометричної точки зору це буде половина діагоналі шуканого ромба}
{Перевіряємо довжини на парність, та місце положення центу (бо якщо довжини рівні і парні, то центр може лежати в нецілій точці)}
if (Distance1 <> Distance2) or (Distance1 mod 2 = 1) or (Distance2 mod 2 = 1) then
T:=Max(Distance1,Distance2) div 2 + Max(Distance1,Distance2) mod 2
else
begin
{Одна відстань рівна іншій і до того ж парна}
if (Points[LeftTopPoint].x + Points[LeftTopPoint].y + Points[RightTopPoint].x + Points[RightTopPoint].y) mod 2 = 0 then
begin
{Центр ромба з діагоналлю Distance1 лежить у цілій точці}
T:=Distance1 div 2;
end
else
begin
{Центр ромба з діагоналлю Distance1 лежить у нецілій точці}
T:=Distance1 div 2 + 1;
end;
end;
write(T);
end.Вибачаюся, цей розвязок я писав заново тому допустив помилку:
if (Distance1 <> Distance2) or (Distance1 mod 2 = 1) or (Distance2 mod 2 = 1) then T:=Max(Distance1,Distance2) div 2 + 1
а треба:
if (Distance1 <> Distance2) or (Distance1 mod 2 = 1) or (Distance2 mod 2 = 1) then T:=Max(Distance1,Distance2) div 2 + Max(Distance1,Distance2) mod 2
Відредаговано Трегубенко Антон (2006-02-08 09:21:29)
Поза форумом
Мені ця задача дуже сподобалась з математичної точки зору. В ній головне - знайти вірний алгоритм, а сам текст программи досить невеликий.
Дякую за увагу. Бажаю всім успіхів.
Поза форумом
Трегубенко Антон:
Щиро дякую.
Поза форумом