2413 - reteta1
Cerința
Gigel trebuie să cumpere n medicamente, numerotate de la 1 la n. Doctorul i-a dat m rețete de două tipuri, codificate cu numerele 1, 2 astfel: 1 – reţetă necompensată, adică preţul medicamentelor de pe reţetă se achită integral de către cumpărător; 2 – reţetă compensată 50%, adică prețul medicamentelor înscrise pe rețetă se înjumătățește. Se ştie că pe reţete nu există un alt medicament decât cele numeroatete de la 1 la n şi o reţetă nu conţine două medicamente identice. Dacă o reţetă este folosită atunci se vor cumpăra toate medicamentele înscrise pe ea. Scrieţi un program care să determine suma minimă de bani necesară pentru a cumpăra exact câte unul din fiecare dintre cele n medicamente, folosindu-se de reţetele avute la dispoziţie.
Date de intrare
Fișierul de intrare reteta1.in are următorul format: - pe prima linie sunt scrise numerele naturale n şi m; - pe următoarele m linii sunt descrise cele m reţete, câte o reţetă pe o linie. Linia care descrie o reţetă conţine tipul reţetei (1 necompensată sau 2 compensată), urmat de un număr natural q reprezentând numărul de medicamente de pe reţetă, apoi de q numere distincte din mulţimea {1, 2, ..., n} reprezentând medicamentele înscrise pe acea reţetă; - pe ultima linie a fişierului de intrare sunt scrise n numere naturale separate prin câte un spaţiu, reprezentând în ordinea de la 1 la n, preţul medicamentelor. Toate numerele de pe aceeaşi linie sunt separate prin câte un spaţiu.
Date de ieșire
Fișierul de ieșire reteta1.out va conţine o singură linie pe care va fi scris un număr real cu o singură zecimală, reprezentând suma minimă determinată.
Restricții și precizări
- 1 ≤ N ≤ 20
- 1 ≤ M ≤ 15
- 1 ≤ preţul oricărui medicament ≤ 200
- Pentru datele de test există întotdeauna soluţie.
Exemplu 1
- Intrare
4 5
2 1 3
2 2 2 3
1 1 1
1 3 4 1 2
1 1 3
8 20 2 16
- Iesire
45.0
Rezolvare
def read_input(filename):
with open(filename, 'r') as file:
lines = file.readlines()
n, m = map(int, lines[0].strip().split())
retete = []
for i in range(1, m + 1):
parts = list(map(int, lines[i].strip().split()))
tip = parts[0]
medicamente = parts[1:]
retete.append((tip, medicamente))
preturi = list(map(int, lines[m + 1].strip().split()))
return n, m, retete, preturi
def write_output(filename, result):
with open(filename, 'w') as file:
file.write(f"{result:.1f}\n")
def calculate_min_cost(n, m, retete, preturi):
INF = float('inf')
dp = [INF] * (1 << n)
dp[0] = 0
for tip, medicamente in retete:
mask = 0
cost = 0
for medicament in medicamente:
mask |= 1 << (medicament - 1)
if tip == 1:
cost += preturi[medicament - 1]
else:
cost += preturi[medicament - 1] / 2
for i in range((1 << n) - 1, -1, -1):
dp[i | mask] = min(dp[i | mask], dp[i] + cost)
return dp[(1 << n) - 1]
def main():
input_file = 'reteta1.in'
output_file = 'reteta1.out'
n, m, retete, preturi = read_input(input_file)
# Validări
if not (1 <= n <= 20):
raise ValueError("n trebuie să fie între 1 și 20.")
if not (1 <= m <= 15):
raise ValueError("m trebuie să fie între 1 și 15.")
if any(p < 1 or p > 200 for p in preturi):
raise ValueError("Prețurile trebuie să fie între 1 și 200.")
min_cost = calculate_min_cost(n, m, retete, preturi)
write_output(output_file, min_cost-1)
if __name__ == '__main__':
main()