Pagini recente » Cod sursa (job #3349458) | Cod sursa (job #3340384) | Cod sursa (job #2723027) | Cod sursa (job #73826) | Cod sursa (job #3333719)
def rezolva():
# citesc datele de intrare din fisier
with open("adn.in", "r") as f:
n = int(f.readline().strip())
secvente = []
for i in range(n):
secvente.append(f.readline().strip())
# elimin secventele care sunt subsiruri ale altor secvente
secvente_filtrate = []
for i in range(n):
este_subsir = False
for j in range(n):
if i != j and secvente[i] in secvente[j]:
este_subsir = True
break
if not este_subsir:
secvente_filtrate.append(secvente[i])
secvente = secvente_filtrate
n = len(secvente)
# caz special: o singura secventa
if n == 1:
with open("adn.out", "w") as f:
f.write(secvente[0] + "\n")
return
# calculez suprapunerea intre fiecare pereche de secvente
# suprapunere[i][j] = cate caractere din sfarsitul lui i se suprapun cu inceputul lui j
suprapunere = []
for i in range(n):
suprapunere.append([0] * n)
for i in range(n):
for j in range(n):
if i == j:
continue
# caut cea mai mare suprapunere intre sfarsitul lui secvente[i] si inceputul lui secvente[j]
lung_max = min(len(secvente[i]), len(secvente[j]))
for k in range(lung_max, 0, -1):
if secvente[i][-k:] == secvente[j][:k]:
suprapunere[i][j] = k
break
# programare dinamica pe masca de biti
# dp[masca][i] = lungimea minima a sirului care contine toate secventele din masca si se termina cu secventa i
inf = float('inf')
dp = []
parinte = [] # pentru reconstructie: parinte[masca][i] = (masca_anterioara, j) - am ajuns de la j la i
for masca in range(1 << n):
dp.append([inf] * n)
parinte.append([(-1, -1)] * n)
# initializez: fiecare secventa singura
for i in range(n):
dp[1 << i][i] = len(secvente[i])
# completez dp
for masca in range(1, 1 << n):
for ultim in range(n):
if not (masca & (1 << ultim)):
continue
if dp[masca][ultim] == inf:
continue
# incerc sa adaug o noua secventa
for urmator in range(n):
if masca & (1 << urmator):
continue
masca_noua = masca | (1 << urmator)
cost_nou = dp[masca][ultim] + len(secvente[urmator]) - suprapunere[ultim][urmator]
if cost_nou < dp[masca_noua][urmator]:
dp[masca_noua][urmator] = cost_nou
parinte[masca_noua][urmator] = (masca, ultim)
# gasesc secventa finala cu lungime minima
masca_finala = (1 << n) - 1
lungime_min = inf
ultim_optim = -1
for i in range(n):
if dp[masca_finala][i] < lungime_min:
lungime_min = dp[masca_finala][i]
ultim_optim = i
# reconstruiesc ordinea secventelor
ordine = []
masca = masca_finala
curent = ultim_optim
while curent != -1:
ordine.append(curent)
masca_ant, ant = parinte[masca][curent]
masca = masca_ant
curent = ant
ordine.reverse()
# construiesc sirul final
rezultat = secvente[ordine[0]]
for i in range(1, len(ordine)):
idx_ant = ordine[i - 1]
idx_curent = ordine[i]
# adaug doar partea care nu se suprapune
suprap = suprapunere[idx_ant][idx_curent]
rezultat += secvente[idx_curent][suprap:]
# scriu rezultatul in fisier
with open("adn.out", "w") as f:
f.write(rezultat + "\n")
rezolva()