3446 - Ateleport

From Bitnami MediaWiki

Marian se află în galaxia OJI-2020 și este anul 11235. În această galaxie există N planete diferite și M canale bidirecţionale de transport de tipul (x, y, t) care îţi permit să te deplasezi de pe planeta x pe planeta y (sau invers) în t secunde.

Dar Marian este un adevărat inginer și, pentru că i se pare foarte ineficientă această metodă de transport, a dezvoltat un dispozitiv care îți permite teleportarea de pe o planetă x pe orice altă planetă y în P secunde cu condiţia că ai putea ajunge pornind de pe planeta x pe planeta y folosind maxim L canale de transport.

Acest dispozitiv este momentan doar un prototip, așa că nu îl poate folosi mai mult de K ori. Marian se află pe planeta 1 și te roagă să îi spui care e timpul minim necesar pentru a ajunge pe planeta N.

Cerința[edit | edit source]

Să se scrie un program care calculează timpul minim necesar pentru a ajunge pe planeta N pornind de pe planeta 1.

Date de intrare[edit | edit source]

Fișierul de intrare ateleport.in conține pe prima linie 5 valori N, M, P, L, K, separate printr-un singur spaţiu, cu semnificaţia din enunţ.

Pe fiecare din următoarele M linii se vor afla câte 3 valori Xi, Yi, Ti care descriu un canal de transport.

Date de ieșire[edit | edit source]

Fișierul de ieșire ateleport.out va conține o singură valoare pe prima linie care reprezintă

timpul minim necesar pentru a ajunge pe planeta N pornind de pe planeta 1.

Restricții și precizări[edit | edit source]

  • 1 < N, M ≤ 10 000;
  • 0 ≤ L, K ≤ 10;
  • 1 < Ti , P ≤ 100 000;
  • 1 < Xi , Yi ≤ N;
  • între oricare două planete există cel mult un canal;
  • pentru teste în valoare de 30 de puncte se garantează că K = 0 și toate canalele de comunicare au Ti = 1;
  • pentru ALTE teste în valoare de 20 de puncte se garantează că K = 0;
  • pentru ALTE teste în valoare de 20 de puncte se garantează că N ≤ 300;
  • se garantează că pentru toate testele există soluţie;
  • în concurs s-au acordat 10 puncte din oficiu. Pe site se acordă 10 puncte pentru exemple.

Exemplul 1[edit | edit source]

ateleport.in

6 7 3 2 1
1 2 2
1 3 5
2 3 4
2 4 23
3 4 6
5 4 7
5 6 9

ateleport.out

14

Explicație[edit | edit source]

Dispozitivul se poate folosi cel mult o dată. Pentru a ajunge pe planeta 6 în timp minim vom parcurge canalul 1 → 2 apoi ne vom teleporta până pe planeta 5 de unde vom mai parcurge canalul 5 → 6. Costul final este 2 + 3(teleportare)  + 9 = 14.

Exemplul 1[edit | edit source]

ateleport.in

6 7 3 2 0
1 2 2
1 3 5
2 3 4
2 4 23
3 4 6
5 4 7
5 6 9

ateleport.out

27

Explicație[edit | edit source]

Dispozitivul nu se poate folosi deloc. Pentru a ajunge pe planeta 6 de pe planeta 1 în timp minim, se vor parcurge canalele în ordinea 1→3→4→5→6 și se obține timpul 5+6+7+9=27 de secunde.

Rezolvare[edit | edit source]

<syntaxhighlight lang="python3"> import heapq

fin = open("ateleport.in", "r") fout = open("ateleport.out", "w")

NMAX = 10001 TMAX = 11

class Muchie:

   def __init__(self, to, cost):
       self.to = to
       self.cost = cost

muchii = [[] for _ in range(NMAX)] timp = [[[float('inf') for _ in range(TMAX)] for _ in range(TMAX)] for _ in range(NMAX)]

def ini(n):

   for i in range(1, n + 1):
       for j in range(11):
           for k in range(11):
               timp[i][j][k] = float('inf')

class Element:

   def __init__(self, nod, tp, p):
       self.nod = nod
       self.tp = tp
       self.p = p
   def __lt__(self, other):
       return timp[other.nod][other.tp][other.p] < timp[self.nod][self.tp][self.p]

def dijkstra(destinatie, l, k, p):

   timp[1][0][0] = 0
   pq = []
   heapq.heappush(pq, Element(1, 0, 0))
   while pq:
       relax = heapq.heappop(pq)
       for it in muchii[relax.nod]:
           # nu ma teleportez
           if timp[it.to][relax.tp][0] > timp[relax.nod][relax.tp][relax.p] + it.cost:
               timp[it.to][relax.tp][0] = timp[relax.nod][relax.tp][relax.p] + it.cost
               heapq.heappush(pq, Element(it.to, relax.tp, 0))
           # incep o teleportare
           if relax.tp < k:
               if timp[it.to][relax.tp + 1][1] > timp[relax.nod][relax.tp][relax.p] + p:
                   timp[it.to][relax.tp + 1][1] = timp[relax.nod][relax.tp][relax.p] + p
                   heapq.heappush(pq, Element(it.to, relax.tp + 1, 1))
           # continui o teleportare
           if relax.p and relax.p < l:
               if timp[it.to][relax.tp][relax.p + 1] > timp[relax.nod][relax.tp][relax.p]:
                   timp[it.to][relax.tp][relax.p + 1] = timp[relax.nod][relax.tp][relax.p]
                   heapq.heappush(pq, Element(it.to, relax.tp, relax.p + 1))
   ans = float('inf')
   for j in range(k + 1):
       for m in range(l + 1):
           ans = min(ans, timp[destinatie][j][m])
   fout.write(str(ans) + '\n')

if __name__ == "__main__":

   n, m, p, l, k = map(int, fin.readline().split())
   ini(n)
   for _ in range(m):
       a, b, c = map(int, fin.readline().split())
       muchii[a].append(Muchie(b, c))
       muchii[b].append(Muchie(a, c))
   dijkstra(n, l, k, p)
   fin.close()
   fout.close()

</syntaxhighlight>