1

Тема: Чому не ідуть всі тести? Допоможіть!

Ось у мова і мій код.
Подiл котiв
Обмеження: 1 сек., 256 МiБ
Зеник та Марiчка недавно купили в Ашанi n нових котiв. Вiдомо, що i-й кiт важить ai кiлограм.
Тепер нашi георї хочуть роздiлити цих котiв мiж собою. Основним для них є те, щоб витрати
на цих котiв були розподiленi однаково мiж друзями. Оскiльки витрати на кота пропорцiйнi його
вазi, вони хочуть роздiлити котiв так, щоб сумарна вага Зеникових котiв була рiвною сумарнiй
вазi котiв Марiчки.
Ваше завдання  допомогти їм знайти шуканий подiл.
Вхiднi данi
У першому рядку задано одне цiле число n кiлькiсть котiв. У другому рядку задано n цiлих чисел ai, роздiлених пробiлами  ваги вiдповiдних котiв. Коти пронумерованi цiлими числами вiд 1 до n включно.
Вихiднi данi:
Якщо правильно роздiлити котiв неможливо, виведiть одне число
-1. Iнакше, у першому рядку виведiть число k кiлькiсть котiв, якi отримає Зеник. У другому
рядку виведiть послiдовнiсть iз k цiлих чисел  iндекси Зеникових котiв. Всi iншi коти отримає
Марiчка. Якщо iснує декiлька правильних розподiлiв, дозволяється вивести будь-який з них.
Обмеження:
1<=n<=200;
1<=ai<=4
Приклад:
Вхідні дані:                                                 Вихідні дані:
5                                                                 3
4 1 4 3 4                                                       1  2  4
Ось код:

var
  n, k, i, s, ostacha, polovina: integer;
  a: array[1..200] of integer;
  index: array[1..200] of integer;

begin
  s := 0;
  readln(n);
  for i := 1 to n do 
  begin
    read(a[i]);
    s := s + a[i];
  end;
  ostacha := s mod 2;
  s := s div 2;
  polovina := a[1]; 
  k := 1;
  index[k] := 1; 
  i := 1;
  if ostacha = 0 then  
    while (polovina <> s) and (i <= n) do 
    begin
      i := i + 1;
      polovina := polovina + a[i];
      if polovina <= s then begin k := k + 1; index[k] := i; end;
      if polovina > s then polovina := polovina - a[i];
    end;
  if (ostacha <> 0) or (polovina < s) then write(-1) else begin
    writeln(k);
    for i := 1 to k do write(index[i], ' ');
  end;
end.

2

Re: Чому не ідуть всі тести? Допоможіть!

Я би радив спочатку відсортувати масив "a" від більшого до меншого. Масив з індексами треба буде перебудувати аналогічним чином. Потім вагу можна буде набирати ідучи від тяжчих котів до легших.

Подякували: bogdandacik1

3

Re: Чому не ідуть всі тести? Допоможіть!

Пане Torbins, якщо від сортувати масив то індекси елементів поміняються. Чи ви маєте на увазі від сортувати масив, далі набирати вагу і фіксувати індекси, а потім одержаний відсортований масив індексів відсортувати в порядку зростання.

4

Re: Чому не ідуть всі тести? Допоможіть!

Взагалі перед тим, як програмувати, слід продумати алгоритм. Простий жадібний алгоритм, вочевидь, не дає відповіді - ось контрприклад:
7,7,4,4,4,4.
Правильна відповідь існує, це 7,4,4, але якщо просто пхати, доки лізе, як у вас, то збираємо 7,7 і далі відповіді немає. В загальному вигляді, я так розумію, задача NP-повна.
Але тут маси котів невеликі, тобто їх можна порахувати в додатковий масив - скільки 1-кг, 2-кг і т.д. котів. Далі треба думати.

Подякували: bogdandacik1

5

Re: Чому не ідуть всі тести? Допоможіть!

Добре, кількість котів різної маси порахувати можна, а що далі з цим робити?

6

Re: Чому не ідуть всі тести? Допоможіть!

Далі - розбирати випадки. Буду позначати кількості c1..c4. Будемо дивитися поки лише на залишки від ділення на 2. Якщо c1 і c3 різної парності, то сума непарна. Лишається 8 варіантів по парності:

№  | по mod 2
       c1 c2 c3 c4
1       0  0  0  0
2       0  0  0  1
3       1  0  1  0
4       1  0  1  1
5       0  1  0  0
6       0  1  0  1
7       1  1  1  0
8       1  1  1  1

Намагаємося всі групи поділити якомога рівніше навпіл і балансуємо:
1. Очевидно
2. Якщо c2>=2 або c1>=1 та c3>=1 або c1>=4, то у відповідь додаємо "зайву" четвірку і забираємо дві двійки чи по одній одинці та трійці чи три одинці (2+1+1 не розглядаємо, бо c2 парне), інакше -1
3. Якщо c4>=1, то у відповідь - зайві 1 та 3 і прибираємо 4; якщо с2>=1, то у відповідь додаємо 3 і віднімаємо 1 та 2; якщо c1>=3, то у відповідь додаємо 3 і забираємо 3 одиниці, інакше -1
4. 4 в одну групу, 1 та 3 - в іншу
5. Якщо c1>=2, то 2 в одну групу, дві одиниці в іншу. Якщо c3>=2 і c4>=1, то в одну групу 4+2, в іншу - 3+3
6. Якщо c1>=2, то в одну групу 2+1+1, в іншу - 4. Якщо с2>=3, то в одну групу 4, в іншу зайву 2. Якщо с3>=2, то в одну групу 3+3, в іншу 2+4.
7. В одну групу 3, в іншу 2+1.
8. В одну групу 1+4, в іншу 2+3.
Якщо ви матимете послідовний список всіх котів і кількість котів кожної ваги для половини, то зможете набрати відповідь?

Подякували: bogdandacik1

7

Re: Чому не ідуть всі тести? Допоможіть!

Підозрюю, що можна це все узагальнити, але і так непогано виходить.

Подякували: bogdandacik1

8

Re: Чому не ідуть всі тести? Допоможіть!

bogdandacik написав:

Пане Torbins, якщо від сортувати масив то індекси елементів поміняються. Чи ви маєте на увазі від сортувати масив, далі набирати вагу і фіксувати індекси, а потім одержаний відсортований масив індексів відсортувати в порядку зростання.

Коли заповнюєте масив А, то заповнюйте іще другий масив з індексами. Потім, коли будете сортувати А, то аналогічні перестановки треба робити й у другому масиві, щоб порядкові номери елементів не загубилися. Коли у вас є відсортований масив ваг, то набрати з нього сумарну задану вагу зовсім не складно.

Подякували: bogdandacik1

9

Re: Чому не ідуть всі тести? Допоможіть!

Написав на Python, після виправлення всі тести пройшов. Трохи схибив у парі випадків, ну то вам теж має бути цікаво пройтися всіма гілками алгоритму :)

10

Re: Чому не ідуть всі тести? Допоможіть!

Torbins написав:
bogdandacik написав:

Пане Torbins, якщо від сортувати масив то індекси елементів поміняються. Чи ви маєте на увазі від сортувати масив, далі набирати вагу і фіксувати індекси, а потім одержаний відсортований масив індексів відсортувати в порядку зростання.

Коли заповнюєте масив А, то заповнюйте іще другий масив з індексами. Потім, коли будете сортувати А, то аналогічні перестановки треба робити й у другому масиві, щоб порядкові номери елементів не загубилися. Коли у вас є відсортований масив ваг, то набрати з нього сумарну задану вагу зовсім не складно.

Я гальмую. Як без повного перебору, чи без мого розбору випадків?

Подякували: bogdandacik1

11

Re: Чому не ідуть всі тести? Допоможіть!

Ну, формально перебір усе одно потрібен, але на сортованому масиві він уже не буде повним. Я це реалізував рекурсивною процедурою, яка збільшує суму, додаючи один елемент. Але вона вміє пропускати елементи, якщо поточний елемент надто великий і потрібну суму побудувати не вдалося.
З таким алгоритмом Зенику дістануться переважно товсті коти, але умова задачі не вимагає підтримувати різноманіття.

Подякували: leofun01, bogdandacik2

12

Re: Чому не ідуть всі тести? Допоможіть!

Дякую за допомогу пане Koala. Не було часу дописати код. Пішли всі тести, ось код:

type
  mas = array[1..200] of integer;

var
  a, index: mas;
  n, i, c1, c2, c3, c4, k, m: integer;
  podil: boolean;

begin
  readln(n);
  c1 := 0; c2 := 0; c3 := 0; c4 := 0;
  for i := 1 to n do 
  begin
    read(a[i]);
    if a[i] = 1 then c1 := c1 + 1;
    if a[i] = 2 then c2 := c2 + 1;
    if a[i] = 3 then c3 := c3 + 1;
    if a[i] = 4 then c4 := c4 + 1;
  end;
  podil := false;
  {0 0 0 0}
  if (c1 mod 2 = 0) and (c2 mod 2 = 0) and (c3 mod 2 = 0) and (c4 mod 2 = 0) then begin
    c1 := c1 div 2;
    c2 := c2 div 2;
    c3 := c3 div 2; 
    c4 := c4 div 2;
    podil := true;
  end;
  {0 0 0 1}
  if (c1 mod 2 = 0) and (c2 mod 2 = 0) and (c3 mod 2 = 0) and (c4 mod 2 = 1) and (c2 >= 2) then begin
    c1 := c1 div 2;
    c2 := c2 - 2;
    c2 := c2 div 2;
    c3 := c3 div 2; 
    c4 := c4 + 1;
    c4 := c4 div 2;
    podil := true;
  end;
  if (podil = false) and (c1 mod 2 = 0) and (c2 mod 2 = 0) and (c3 mod 2 = 0) and 
       (c4 mod 2 = 1) and (c1 >= 2) and (c3 >= 2)
  then 
  begin
    c1 := c1 div 2 + 1; 
    c2 := c2 div 2;
    c3 := c3 div 2 - 1;
    c4 := c4 div 2 + 1;
    podil := true;
  end;
  {1 0 1 0}
  if (podil = false) and (c1 mod 2 = 1) and (c2 mod 2 = 0) and (c3 mod 2 = 1) 
      and (c4 mod 2 = 0) and (c4 >= 2) and (c2 = 0) and (c3 >= 3) then 
  begin
    c1 := c1 div 2;
    c3 := (c3 div 2) + 2;
    c4 := (c4 div 2) - 1;
    podil := true;
  end;
  if (podil = false) and (c1 mod 2 = 1) and (c2 mod 2 = 0) and (c3 mod 2 = 1) 
      and (c4 mod 2 = 0) and (c2 >= 2) then 
  begin
    c1 := c1 div 2;
    c2 := (c2 div 2) + 1;
    c3 := (c3 div 2);
    c4 := c4 div 2;
    podil := true;
  end;
  if (podil = false) and (c1 mod 2 = 1) and (c2 mod 2 = 0) and (c3 mod 2 = 1) 
      and (c4 mod 2 = 0) and (c4 = 0) and (c2 = 0) and (c1 >= 3) then 
  begin
    c1 := (c1 div 2) + 2;
    c3 := c3 div 2;
    podil := true;
  end;
   {1 0 1 1}  
  if (podil = false) and (c1 mod 2 = 1) and (c2 mod 2 = 0) and (c3 mod 2 = 1) 
      and (c4 mod 2 = 1) then 
  begin
    c1 := (c1 div 2) + 1;
    c2 := c2 div 2;
    c3 := (c3 div 2) + 1;
    c4 := c4 div 2;
    podil := true;
  end;
   {0 1 0 0}  
  if (podil = false) and (c1 mod 2 = 0) and (c2 mod 2 = 1) and (c3 mod 2 = 0) 
      and (c4 mod 2 = 0) and (c1 >= 2) then   
  begin
    c1 := (c1 div 2) + 1;
    c2 := c2 div 2;
    c3 := c3 div 2;
    c4 := c4 div 2;
    podil := true;
  end;
  if (podil = false) and (c1 mod 2 = 0) and (c2 mod 2 = 1) and (c3 mod 2 = 0) 
      and (c4 mod 2 = 0) and (c1 = 0) and (c3 >= 2) and (c4 >= 2) then 
  begin
    c2 := c2 div 2;
    c3 := (c3 div 2) - 1;
    c4 := (c4 div 2) + 1;
    podil := true;
  end;
  if (podil = false) and (c1 mod 2 = 0) and (c2 mod 2 = 1) and (c3 mod 2 = 0) 
      and (c4 mod 2 = 0) and (c1 = 0) and (c3 >= 2) and (c4 = 0) then 
  begin
    c2 := (c2 div 2) + 2;
    c3 := (c3 div 2) - 1;
    podil := true;
  end;
      {0 1 0 1}
  if (podil = false) and (c1 mod 2 = 0) and (c2 mod 2 = 1) and (c3 mod 2 = 0) 
      and (c4 mod 2 = 1) and (c1 >= 2) then 
  begin
    c1 := (c1 div 2) + 1;
    c2 := (c2 div 2) + 1;
    c3 := c3 div 2;
    c4 := c4 div 2;
    podil := true;
  end;
  if (podil = false) and (c1 mod 2 = 0) and (c2 mod 2 = 1) and (c3 mod 2 = 0) 
      and (c4 mod 2 = 1) and (c1 = 0) and (c2 >= 1) and (c3 >= 2) then 
  begin
    c2 := c2 div 2;
    c3 := (c3 div 2) + 1;
    c4 := c4 div 2;
    podil := true;
  end;
      {1 1 1 0}
  if (podil = false) and (c1 mod 2 = 1) and (c2 mod 2 = 1) and (c3 mod 2 = 1) 
      and (c4 mod 2 = 0) then 
  begin
    c1 := (c1 div 2) + 1;
    c2 := (c2 div 2) + 1;
    c3 := c3 div 2;
    c4 := c4 div 2;
    podil := true;
  end;
      {1 1 1 1}
  if (podil = false) and (c1 mod 2 = 1) and (c2 mod 2 = 1) and (c3 mod 2 = 1) 
      and (c4 mod 2 = 1) then 
  begin
    c1 := (c1 div 2) + 1;
    c2 := c2 div 2;
    c3 := c3 div 2;
    c4 := (c4 div 2) + 1;
    podil := true;
  end;
  
  k := c1 + c2 + c3 + c4;
  m := 1;
  for i := 1 to n do 
  begin
    if (a[i] = 1) and (c1 > 0) then  begin index[m] := i; c1 := c1 - 1; m := m + 1; end;
    if (a[i] = 2) and (c2 > 0) then  begin index[m] := i; c2 := c2 - 1; m := m + 1; end;
    if (a[i] = 3) and (c3 > 0) then  begin index[m] := i; c3 := c3 - 1; m := m + 1; end;
    if (a[i] = 4) and (c4 > 0) then  begin index[m] := i; c4 := c4 - 1; m := m + 1; end;
    
  end;

13 Востаннє редагувалося koala (21.02.2019 13:53:27)

Re: Чому не ідуть всі тести? Допоможіть!

Змінну podil ви замість else використовуєте?
Якщо замість чотирьох змінних c1-c4 ввести масив з [1..4], можна буде робити

  for i := 1 to n do 
  begin
    read(a[i]);
    c[a[i]] = c[a[i]] + 1;
  end;

і т.д.

14

Re: Чому не ідуть всі тести? Допоможіть!

Мені здається, що так простіше:

Прихований текст
var
  N, NSort, k, i, Sum, Ostacha, Polovina, Temp: integer;
  MasVaga: array[1..200] of integer;
  IndexVaga, IndexRes: array[1..200] of integer;
  GoSort: Boolean;

  function BuildSum(CSum, CVagaInd, CResInd: Integer): Boolean;
  var
    LSum, j, NextInd: Integer;
    SubRes: Boolean;
  begin
    BuildSum := False;
    if CVagaInd > N then
      Exit;

    LSum := CSum + MasVaga[CVagaInd];
    if LSum < Polovina then
    begin
      SubRes := BuildSum(LSum, CVagaInd + 1, CResInd + 1);
      if SubRes then
      begin
        BuildSum := True;
        IndexRes[CResInd] := IndexVaga[CVagaInd];
        Exit;
      end;
    end
    else
      if LSum = Polovina then
      begin
        BuildSum := True;
        k := CResInd;
        IndexRes[CResInd] := IndexVaga[CVagaInd];
        Exit;
      end;

    // елементи поточного розміру не підходять, шукаємо менші
    NextInd := 0;
    for j := CVagaInd + 1 to N do
      if MasVaga[CVagaInd] > MasVaga[j] then
      begin
        NextInd := j;
        Break;
      end;
    if NextInd > 0 then
      BuildSum := BuildSum(CSum, NextInd, CResInd);
  end;

begin
  Sum := 0;
  readln(N);
  for i := 1 to N do
  begin
    read(MasVaga[i]);
    Sum := Sum + MasVaga[i];
    IndexVaga[i] := i;
  end;
  Ostacha := Sum mod 2;

  NSort := N;
  GoSort := true;
  while GoSort = true do
  begin
    GoSort := false;
    for i:=1 to NSort-1 do
      if MasVaga[i]<MasVaga[i+1] then
      begin
        Temp := MasVaga[i];
        MasVaga[i] := MasVaga[i+1];
        MasVaga[i+1] := Temp;
        Temp := IndexVaga[i];
        IndexVaga[i] := IndexVaga[i+1];
        IndexVaga[i+1] := Temp;
        GoSort := true;
      end;
    dec(NSort);
  end;

  Polovina := Sum div 2;
  if (Ostacha > 0) or not BuildSum(0, 1, 1) then
    write(-1)
  else
  begin
    writeln(k);
    for i := 1 to k do
      write(IndexRes[i], ' ');
  end;
end.