Подразделы

Другие разделы

Дата и время

28/01/2020 03:34:22

Авторизация

Имя:
Пароль:
Зарегистрироваться
Восстановить пароль
 

printРазбор решений

A. Будильник
Тема: простая задача

В зависимости от значений введенных `S` и `T` вывести либо разность `T-S` либо `T+12-S`.
var s,t:integer;
begin
  assign(input,'input.txt');
  assign(output,'output.txt');
  reset(input);
  rewrite(output);
  read(s,t);
  if s<=t then writeln(t-s)
  else writeln(t+12-s);
  close(input);
  close(output);
end.


B. Калах
Тема: техническая задача, моделирование

Для хранения текущего состояния игры будем использовать массив `d`:
  d:array[1..2, 1..7] of integer;
Номер игрока, делающего ход, хранится в переменной `h`:
  h:integer;
Инициализируем эти переменные следующим образом:
for s:=1 to 2 do
begin
  for i:=1 to 6 do
    d[s,i]:=3;
  d[s,7]:=0;
end;
h:=1;
Для каждого хода выполняем следующие действия:
var s, { текущая сторона калаха }
    k, { камни в руке }
    p:integer; { номер текущей лунки }
...
{ считываем номер лунки }
read(p);
{ забираем все камни из лунки }
k:=d[h,p];
d[h,p]:=0;
{ начиная со следующей лунки }
inc(p);
s:=h; 
while true do
  begin
    { кладем камень }
    inc(d[s,p]); 
    dec(k);
    { камней не осталось - выходим из цикла }
    if k=0 then break;
    inc(p);
    if (p>7) or (p>6) and (s<>h) { дошли до калаха } then
    begin
      s:=3-s; { Переходим на другую сторону}
      p:=1;
    end;
  end;
Когда камни разложены, проверяем условия на специальные ходы:
if (s=h) and (d[h,p]=1) and (p<7) and (d[3-h,7-p]>0) then
  { положили последний камень в пустую лунку на своей стороне }
  begin
    { перекладываем камни в калах из своей и противоположной лунок }
    d[h,7]:=d[h,7]+d[3-h,7-p]+d[h,p];
    d[h,p]:=0;
    d[3-h,7-p]:=0;
  end;
{ если последний камень попал не в свой калах - передаем ход }
if p<>7 then 
  h:=3-h;
После обработки всех ходов выводим состояние лунок:
for s:=1 to 2 do
  begin
    for i:=1 to 6 do
      write(d[s,i],' ');
    writeln(d[s,7]);
  end;


С. Саванна
Тема: поиск в глубину

Для работы потребуются следующие переменные:
var n, { количество животных }
  d,   { максимальное расстояние между животными одного стада }
  k,   { количество стад }
  i:longint;

  x,y:array[1..1000] of longint; { координаты животных }

  f:array[1..1000] of boolean; { флажки - животное отнесено к какому-то стаду }
Эти переменные инициализируются следующим образом:
read(n,d);
for i:=1 to n do
  begin
    read(x[i],y[i]);
    f[i]:=false;
  end;
k:=0;
Для отнесения животного к какому-то стаду используем рекурсивную подпрограмму:
procedure dfs(i:integer);
var j:integer;
begin
  if f[i] then exit; { уже классифицировали - выходим }
  f[i]:=true; { отмечаем флажком }
  for j:=1 to n do 
    { для всех животных на расстоянии не более D }
    if sqr(x[i]-x[j])+sqr(y[i]-y[j])<=sqr(d) then
      dfs(j); { делаем те же действия }
end;
Теперь для всех непомеченных животных вызываем эту подпрограмму и увеличиваем счетчик стад `k`:
for i:=1 to n do
  if not f[i] then
    begin
      inc(k);
      dfs(i);
    end;
После завершения цикла выводим значение `k`.


D. Возрастающие числа
Тема: динамическое программирование

Все возможные "возрастающие числа" занесем в массив `"num"` в лексикографическом порядке:
type numinf=record val,len:longint; end;
const num:array[1..39] of numinf=(
(val:1;len:2),(val:123;len:4),(val:1234;len:4),
  (val:12345;len:4),(val:123456;len:4),(val:12;len:3),
(val:2;len:2),(val:234;len:4),(val:2345;len:4),
  (val:23456;len:4),(val:234567;len:4),(val:23;len:3),
...
(val:8;len:2),(val:89;len:3),
(val:9;len:2));
Минимальную длину будем получать в массиве `"minlen"`:
  minlen:array[0..1000000] of longint;
который нужно инициализировать следующим образом:
for i:=1 to n do { для значений, которые еще не обработаны }
  minlen[i]:=1000000; { установить достаточно большое число }
minlen[0]:=0; { 0 можно получить с помощью строки нулевой длины }
Теперь, двигаясь по таблице от 0 до `n`, узнаем самую короткую длину разложения числа `i` на возрастающие числа. Используется принцип динамического программирования: из оптимального решения подзадач можно получить оптимальное решение всей задачи.
for i:=0 to n do
  begin
    { добавляем к лучшему способу получения числа i
      все возможные возрастающие числа }
    for j:=1 to 39 do
      begin
        k:=i+num[j].val;
        { получаем новый способ получения числа k }
        if (k<=n) and (minlen[k]>minlen[i]+num[j].len) then
           { если длина этого способа меньше, запоминаем его в массиве }
          minlen[k]:=minlen[i]+num[j].len;
      end;
  end;
Обратная трассировка по массиву `"minlen"`:
s:='';
while n>0 do
  begin
    { рассматриваем возрастающие числа в лексикографическом порядке }
    for j:=1 to 39 do
      begin
        k:=n-num[j].val;
        if (k>=0) and (minlen[k]+num[j].len=minlen[n]) then
          { если с помощью этого числа получается способ,
            дающий нужную минимальную длину, 
            то используем именно это число }
          begin
            { добавляем возрастающее число к строке-результату }
            str(num[j].val,ss);
            if length(ss)<=2 then
              s:=s+ss+'+'
            else
              s:=s+ss[1]+'-'+ss[length(ss)]+'+';
            n:=k; { уменьшаем искомое число на возрастающее число }
            break;
          end;
      end;
  end;
{ выводим строку-результат без последнего символа '+' }
writeln(copy(s,1,length(s)-1));

loading