Зарядка за мобільний телефон


10

Виклик, прийнятий з дозволу мого університетського конкурсу викликів


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

Я одна з них.

Протягом багатьох років я вдосконалював свою техніку, щоб не заряджати батарею до максимуму щовечора. Зі своїми ідеально відомими процедурами, що повторюються, я зрозумів, в який час доби я зможу робити ті часткові заряди (і на скільки одиниць рівень збільшиться) та що знизить рівень заряду акумулятора між кожним зарядом. За допомогою цих даних щовечора я підраховую мінімальний рівень заряду акумулятора, який я маю вийти з дому наступного дня, щоб він ніколи не опускався нижче мого самонав’язаного порогу в два одиниці.

Те, що я ще не встиг освоїти, - це той самий розрахунок, коли я покидаю встановлену процедуру і у мене є кілька альтернатив, щоб робити речі. Це трапляється, наприклад, у дні, коли я рухаюся в інше місто, до якого я можу приїхати різними шляхами.

У своєму першому підході до проблеми я припускаю, що хочу рухатися навколо «шахової дошки», починаючи з лівого верхнього кута до правого нижнього кута. У кожній "комірці" я можу або зарядити мобільний телефон певною сумою, або не можу, і рівень його навантаження знизиться.

Виклик

Враховуючи матрицю цілих чисел FxC, виведіть мінімальний об'єм акумулятора, який мені потрібно перейти з лівого верхнього кута в правий нижній кут, без того, щоб рівень навантаження ніколи не опускався нижче 2 одиниць.

У матриці позитивне число вказує, скільки я можу зарядити свій мобільний телефон, перш ніж мені доведеться відновити свій шлях, тоді як негативне число вказує на відсутність розетки і що на цю суму акумулятор мобільного телефону знижує рівень заряду. Гарантується, що величини у вихідній та кінцевій клітинках (у верхньому лівому та нижньому правому куті) завжди дорівнюють 0, а решта значень (абсолютна величина) не перевищує 100.

Приклад наведено
:

[📱-11-1-1-1-1-1-11-1-111-10]

Шлях, який мені потрібно менше акумулятора:

[📱-11-1-1-1-1-1-11-1-111-10]

А мінімальний мій рівень акумулятора, який мені потрібен, - 4

Примітки

  • "Старт" завжди буде у верхньому лівому куті
  • Кінець завжди буде в нижньому правому куті
  • Ви не можете перейти до осередку, який ви вже пройшли. Приклад: Отримавши позицію (0,1), ви не можете перейти до початкової точки (0,0)
  • Рівень акумулятора не може (з будь-якої причини) не перевищувати 2
  • Можна припустити, що завжди буде початок і кінець
  • Ви можете прийняти одновимірні масиви як багатовимірні, якщо вам потрібно [1,2,3] == [[1,2,3]]
  • Існує кілька правильних (мінімально необхідних зарядів) шляхів
  • Ваша мета - вивести лише найнижчий необхідний початковий рівень акумулятора, а не маршрут
  • Можна йти лише вертикально і горизонтально (не по діагоналі)

Випробування

[0, 0] => 2
[0, 1, 0] => 2
[0, -1, 0] => 3
[0, 15, -20, 5, 0] => 7
[[0, -3],[-5, 0]] => 5
[[0, -5, -9, 5], [-3, 5, 2, -2], [2, -4, -4, 0]] => 5
[[0, -1, 1, -1], [-1, -1, -1, -1], [-1, 1, -1, -1], [1, 1, -1, 0]] => 4

Я забув день виклику. Пост в пісочниці
Luis felipe De

Нікому не пам’ятаєш: виклик «Голодний лось» ніколи не виходив із пісочниці, тож це не дурня.
Чорна сова Кай

@BlackOwlKai Я думаю, що обидва виклики різні
Luis felipe De

1
Чи потребуватиме оптимального шляху колись рухатися вліво чи вгору? Наприклад[[0,1,-1],[-9,-9,1],[-9,1,-1],[-9,-1,-9],[-9,1,0]]
Каміль Дракарі

1
@dana ні, є лише два 0sрозміщених у верхньому лівому куті, а другий у нижньому правому куті
Luis felipe De

Відповіді:


3

JavaScript (ES7),  162 156  154 байт

m=>(M=g=(x,y,n,k)=>m.map((r,Y)=>[r[x+1]]+[m[y+1]]?r.map((v,X)=>r[1/v&&(x-X)**2+(y-Y)**2==1&&g(X,Y,u=v+n,k<u?k:u,r[X]=g),X]=v):M=M>k?M:k))(0,0,0)|M<0?2-M:2

Спробуйте в Інтернеті!

Прокоментував

m => (                          // m[] = input matrix
  M =                           // initialize M to a non-numeric value
  g = (x, y, n, k) =>           // g = recursive depth-first search function
    m.map((r, Y) =>             // for each row r[] at position Y in m[]:
      [r[x + 1]] +              //   if either r[x + 1]
      [m[y + 1]] ?              //   or m[y + 1] is defined:
        r.map((v, X) =>         //     for each value v at position X in r[]:
          r[                    //
            1 / v &&            //       if v is numeric
            (x - X) ** 2 +      //       and the squared Euclidean distance
            (y - Y) ** 2 == 1   //       between (x, y) and (X, Y) is 1:
            &&                  //
              g(                //         do a recursive call:
                X, Y,           //           with (X, Y)
                u = v + n,      //           with n = n + v
                k < u ? k : u,  //           with k = min(k, n + v)
                r[X] = g        //           set r[X] to a non-numeric value
              ),                //         end of recursive call
            X                   //       then restore r[X]
          ] = v                 //       to its initial value
        )                       //     end of inner map()
      :                         //   else (we've reached the bottom right corner):
        M = M > k ? M : k       //     update M to max(M, k)
    )                           // end of outer map()
)(0, 0, 0) |                    // initial call to g with x = y = n = 0 and k undefined
M < 0 ? 2 - M : 2               // return 2 - M if M is negative, or 2 otherwise

3

Python 2 , 208 202 байт

lambda s:2-f(s)
def f(s,x=0,y=0):
 if x>-1<y<s[y:]>[]<s[y][x:]!="">s[y][x]:k=s[y][x];s[y][x]="";return k+min(0,max([len(s[y+1:]+s[y][x+1:])and f(eval(`s`),x+a/3-1,y+a%3-1)for a in 7,1,5,3]))
 return-9e9

Спробуйте в Інтернеті!


Python 2 , 217 211 байт

i=input()
X,Y=len(i[0]),len(i)
s=[[0]*4+[i]];r=[]
for m,l,x,y,g in s:
 if X>x>-1<y<Y<"">g[y][x]:r+=[m]*(Y-y<2>X-x);l+=g[y][x];g[y][x]="";s+=[[min(m,l),l,x+a/3-1,y+a%3-1,eval(`g`)]for a in 7,1,5,3]
print 2-max(r)

Спробуйте в Інтернеті!



1

C # (Visual C # Interactive Compiler) , 242 байти

a=>{int m=1<<31,n=~m;void g(int w,int x,int y,int z){for(int i=4,t,c,d,e;i-->0;)try{t=a[c=i<1?w-1:i<2?w+1:w,d=i>2?x-1:i>1?x+1:x];n=t==0&z<n?z:n;a[c,d]=m;e=y+t<2?2-y-t:0;if(t!=m)g(c,d,y+t+e,z+e);a[c,d]=t;}catch{}}a[0,0]=m;g(0,0,2,2);return n;}

Спробуйте в Інтернеті!

//a: input matrix
a=>{
  // m: marker for used cells
  // n: result, initialized to a huge value
  int m=1<<31,n=~m;
  // recursive function
  // w: 1st dim coordinate
  // x: 2nd dim coordinate
  // y: current charge level
  // z: initial charge for current path
  void g(int w,int x,int y,int z){
    // i: loop variable
    // t: temp holds overwritten value
    // c: adjacent 1st dim coordinate
    // d: adjacent 2nd dim coordinate
    // e: delta charge needed
    for(int i=4,t,c,d,e;i-->0;)
      // avoid index out of range errors
      // by using try/catch
      try{
        // determine neighbor
        // coordinates and save value
        t=a[c=i<1?w-1:i<2?w+1:w,
            d=i>2?x-1:i>1?x+1:x];
        // if we have found a 0, check if
        // initial charge is lower than the
        // lowest so far. save it if it is.
        n=t==0&z<n?z:n;
        // mark current cell used
        a[c,d]=m;
        // determine if we need to
        // increase the initial charge
        e=y+t<2?2-y-t:0;
        // make recursive call if current
        // cell was not previously in use
        if(t!=m)g(c,d,y+t+e,z+e);
        // restore current cell value
        a[c,d]=t;
      }catch{}
  }
  // mark starting cell used
  a[0,0]=m;
  // start the recursive function
  g(0,0,2,2);
  // return the result to the caller
  return n;
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.