1225 - Sort 2 Dist

From Bitnami MediaWiki

Jocul pe care îl joaca Robo atunci când se plictisește este un joc inteligent pentru roboței. Pe ecranul tabletei lui roboțești, sunt N căsuțe de formă pătrată, cu latura egală cu 1. Căsuțele sunt așezate pe un rând, una lângă alta, fiind etichetate, în această ordine, cu numere de la 1 la N. Fiecare căsuță conține câte un număr natural, identificatorul câte unuia dintre prietenii săi, roboței, ca și el. Identificatorii se pot repeta.

Robo poate interschimba conținutul a două căsuțe, numai dacă distanța dintre centrele acestora pe orizontală este egală cu distanța dintre brațele sale; distanța, pe orizontală, dintre centrele a două căsuțe etichetate cu i, respectiv cu j, este j-i (1≤i<j≤N).

El își poate fixa în orice moment distanța dintre brațe la 1 sau își poate dubla distanța curentă dintre brațe, de oricâte ori este necesar, fără a depăși valoarea N-1. Astfel, distanța dintre brațele sale poate fi 1, apoi, prin dublare, 2, apoi, prin dublare 4, apoi, prin dublare 8 etc. La începutul jocului, distanța dintre brațele lui Robo este 1. De fiecare dată când consideră convenabilă distanța dintre brațe, realizează o interschimbare.

Cerința[edit | edit source]

Se cere ca Robo să așeze identificatorii în căsuțe în ordine crescătoare, prin maximum 12500 interschimbări de tipul celei precizate mai sus.

Date de intrare[edit | edit source]

Fișierul de intrare sort2distIN.txt conține:

  • pe prima linie numărul natural N, cu semnificația din enunț;
  • pe următoarele N linii, N numere, reprezentând, în această ordine, identificatorii aflați în căsuțele tabletei (identificatorul de pe linia i se află în căsuța i-1).

Date de ieșire[edit | edit source]

Fișierul de ieșire sort2distOUT.txt va conține:

  • pe prima linie un număr natural M, reprezentând numărul de interschimbări realizate de Robo (nu neapărat numărul minim de interschimbări necesare);
  • pe fiecare dintre următoarele M linii (doar dacă M este nenul), câte două numere naturale, separate prin câte un spațiu, reprezentând etichetele căsuțelor al căror conținut s-a interschimbat, în ordinea realizării acestor interschimbări. În cazul în care restricțiile nu sunt îndeplinite, se va afișa mesajul "Datele nu corespund restrictiilor impuse".

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

  • 1 ≤ N ≤ 1000;
  • identificatorii sunt numere naturale de maximum 30 de cifre;
  • pentru 25% din punctaj, fișierele de test conțin numere cu maximum 18 cifre;
  • pentru 25% din punctaj, N ≤ 100.

Exemplul 1 :[edit | edit source]

sort2distIN.txt

4
5
7
6
2

sort2distOUT.txt

2
2 4
2 1

Explicație[edit | edit source]

Tableta are 4 căsuțe, conținând, în această ordine, identificatorii (5,7,6,2).

Pentru ordonarea crescătoare s-au realizat 2 interschimbări:

  • s-a interschimbat conținutul căsuțelor 2 și 4 (distanța dintre centrele lor fiind 2), identificatorii din căsuțe fiind acum (5, 2, 6, 7);
  • s-a interschimbat conținutul căsuțelor 1 și 2 (distanța dintre centrele lor fiind 1), identificatorii din căsuțe fiind acum (2, 5, 6, 7), ordonați crescător.

Exemplul 2 :[edit | edit source]

sort2distIN.txt

1001
5
7
6
2

sort2distOUT.txt

Datele nu corespund restrictiilor impuse

Rezolvare[edit | edit source]

<syntaxhighlight lang="python" line="1"> import os

DIM = 1010

sol = [] v = [0] * DIM s = [""] * DIM aux = "" w = [""] * DIM

def myStrcmp(s1, s2):

   if len(s1) == len(s2):
       return (s1 > s2) - (s1 < s2)
   else:
       return -1 if len(s1) < len(s2) else 1

def schimba(x, y):

   sol.append((x, y))
   aux = v[x]
   v[x] = v[y]
   v[y] = aux

def verify_restrictions(n, strings):

   if not (1 <= n <= 1000):
       return False
   for string in strings:
       if not (1 <= len(string) <= 30):
           return False
   return True

def main():

   with open("sort2distIN.txt", "r") as fin:
       n = int(fin.readline().strip())
       for i in range(1, n + 1):
           s[i] = fin.readline().strip()
           w[i] = s[i]
   if not verify_restrictions(n, s[1:n+1]):
       with open("sort2distOUT.txt", "w") as fout:
           fout.write("Datele nu corespund restrictiilor impuse")
       return
   for i in range(1, n):
       for j in range(i + 1, n + 1):
           if myStrcmp(w[i], w[j]) > 0:
               w[i], w[j] = w[j], w[i]
   k = 1
   for i in range(2, n + 1):
       if myStrcmp(w[i], w[k]) != 0:
           k += 1
           w[k] = w[i]
   for i in range(1, n + 1):
       st = 1
       dr = k
       while st <= dr:
           mid = (st + dr) // 2
           if myStrcmp(s[i], w[mid]) == 0:
               v[i] = mid
               break
           if myStrcmp(s[i], w[mid]) < 0:
               dr = mid - 1
           else:
               st = mid + 1
   for i in range(n, 1, -1):
       m = v[1]
       p = 1
       for j in range(2, i + 1):
           if v[j] > m:
               m = v[j]
               p = j
       if p != i:
           d = i - p
           putere = 1
           last = p
           while d != 0:
               if d % 2 == 1:
                   schimba(last + putere, last)
                   last += putere
               d = d // 2
               putere *= 2
   with open("sort2distOUT.txt", "w") as fout:
       fout.write(f"{len(sol)}\n")
       for x, y in sol:
           fout.write(f"{x} {y}\n")

if __name__ == "__main__":

   main()

</syntaxhighlight>