Olimpiadi di Informatica 2009 Giornate preparatorie

Documenti analoghi
Introduzione all'algoritmica per i Licei (C++). 2 Massimo e minimo.

6 - Blocchi e cicli. Programmazione e analisi di dati Modulo A: Programmazione in Java. Paolo Milazzo

Errori frequenti Cicli iterativi Array. Cicli e array. Laboratorio di Programmazione I. Corso di Laurea in Informatica A.A.

Fondamenti di Informatica T-1 Modulo 2

public static boolean occorre (int[] a, int n) { int i = 0; boolean trovato = false;

Informatica/ Ing. Meccanica/ Ing. Edile/ Prof. Verdicchio/ 05/02/2014/ Foglio delle domande / VERSIONE 1

Esercitazione Fondamenti di Informatica 2

COMANDI ITERATIVI. Ivan Lanese

Corso di Laurea Ingegneria Informatica Fondamenti di Informatica

Informatica/ Ing. Meccanica e Ing. Edile/ Prof. Verdicchio/ 16/07/2013 / Foglio delle domande / VERSIONE 1

Esercizi di Algoritmi e Strutture Dati

Le strutture di controllo in C++

Istruzioni di Ciclo. Unità 4. Domenico Daniele Bloisi. Corso di Programmazione e Metodi Numerici Ingegneria Aerospaziale BAER

9 - Array. Programmazione e analisi di dati Modulo A: Programmazione in Java. Paolo Milazzo

INFORMATICA A. Titolo presentazione sottotitolo. Laboratorio n 6 Dott. Michele Zanella Ing. Gian Enrico Conti

Note per la Lezione 6 Ugo Vaccaro

Lezione di Laboratorio di Prgrammazione: /05/2019 a.a. 2018/2019 R.Prevete

Università degli Studi di Cassino Corso di Fondamenti di Informatica Tipi strutturati: Stringhe. Anno Accademico 2010/2011 Francesco Tortorella

Informatica/ Ing. Meccanica/ Ing. Edile/ Prof. Verdicchio/ 02/04/2014/ Appello straordinario/ Foglio delle domande / VERSIONE 1

Informatica A aa Seconda prova in itinere. Esempi di esercizi possibili

ERRATA CORRIGE. void SvuotaBuffer(void); void SvuotaBuffer(void) { if(getchar()!=10) {svuotabuffer();} }

UNIVERSITA DEGLI STUDI ROMA TRE DIPARTIMENTO DI MATEMATICA E FISICA

Fondamenti di Programmazione

Fondamenti di Informatica

come segue: data una collezione C di elementi e una un elemento che verifica la proprietà P

cout << "Inserisci un numero:" << endl; cin >> n; ris = n*2; cout << "Il doppio di " << n << " e " << ris << endl;

Esercitazione 4. Comandi iterativi for, while, do-while

Fondamenti di Informatica

Laboratorio di Python

Corso di Fondamenti di Informatica Algoritmi su array / 1

14 - Metodi e Costruttori

Indice. I costrutti decisionali I cicli

Programmazione ricorsiva.

Tipi di dato personalizzati Array di struct. Tipi di dato utente. Laboratorio di Programmazione I. Corso di Laurea in Informatica A.A.

Corso di Laboratorio di Sistemi Operativi A.A

Programmazione ricorsiva: cenni

Inserimento in una lista ordinata

Informatica (A-K) 5. Algoritmi e pseudocodifica

Programmazione Procedurale in Linguaggio C++

Variabili. Unità 2. Domenico Daniele Bloisi. Corso di Programmazione e Metodi Numerici Ingegneria Aerospaziale BAER

Fondamenti di Informatica 6. Algoritmi e pseudocodifica

CENNI MINIMI DI PROGRAMMAZIONE FUNZIONALE IN PYTHON - V. 0.3

d. Cancellazione del valore 5 e. Inserimento del valore 1

Laboratorio di Algoritmi e Strutture Dati

Programmazione in Java (I modulo)

Corso di Fondamenti di Programmazione canale E-O. Un esempio. Funzioni ricorsive. La ricorsione

PASCAL LA SELEZIONE: IF TRATTO DA CAMAGNI-NIKOLASSY, CORSO DI INFORMATICA, VOL. 1, HOEPLI. Informatica

Introduzione al linguaggio C Puntatori

C: panoramica. Violetta Lonati

Fondamenti di Informatica

L organizzazione dei programmi

Array. Walter Didimo

Allenamento alle Olimpiadi di Informatica

Stringhe ed Array. Fondamenti di Informatica A-K

UNIVERSITA DEGLI STUDI ROMA TRE DIPARTIMENTO DI MATEMATICA E FISICA

LE STRUTTURE DATI DINAMICHE: GLI ALBERI. Cosimo Laneve

Approcci nella soluzione di un problema

Quadrato Magico. Fondamenti di Programmazione

Corso di Fondamenti di Informatica Tipi strutturati: Stringhe

Ricorsione. Stefano Ferrari. Università degli Studi di Milano Programmazione. anno accademico

Note per la Lezione 7 Ugo Vaccaro

Calcolare x n = x x x (n volte)

12 Function Handles e Ricorsione in MATLAB

Le Funzioni e la Ricorsione

Esercitazione 11. Liste semplici

Esercitazione 6. Array

Fondamenti di Informatica. Algoritmi di Ricerca e di Ordinamento

Un po di Matematica. Il volo dei numeri di Mario Merz, un'installazione luminosa sulla Mole Antonelliana, rappresenta la successione di Fibonacci

Laboratorio di Programmazione M-Z

Tipi strutturati - struct

Programmazione ricorsiva: cenni

RICORSIONE, PUNTATORI E ARRAY. Quarto Laboratorio

Lezione 6 programmazione in Java

Laboratorio di Python

La Ricorsione. Carla Binucci e Walter Didimo

3 aprile o Esonero: mercoledi 17 aprile ore 11:30 14:00 consulta la pag. WEB alla voce esoneri. si raccomanda la puntualita!

Fondamenti di Informatica Ing. Biomedica

PARTE

Programmazione dinamica

ARRAY E STRINGHE. ESERCIZIO 2 Scrivere un programma che calcola il numero di doppie e di dittonghi (2 vocali vicine) presenti in una stringa.

I numeri rossi sulla Mole Antonelliana a Natale. Algoritmi e Laboratorio a.a Lezioni. Le regole della riproduzione dei conigli.

Introduzione al C Lez. 4. Allocazione Dinamica della memoria

Informatica! Appunti della lezione 8!

Strutture di controllo iterative

1) Somma dei primi n numeri naturali: 3) Ricerca di un elemento el in una sequenza di interi: FONDAMENTI DI INFORMATICA II Ricorsione 2

Esercizi su array di array

Array di array. Corso di Laurea Ingegneria Informatica Fondamenti di Informatica 1. Dispensa 03. A. Miola Febbraio 2008

Corso di Informatica

Fondamenti di Informatica 1. Prof. B.Buttarazzi A.A. 2010/2011

Corso di Laurea Ingegneria Informatica Fondamenti di Informatica 2

FUNZIONI RICORSIVE PROGRAMMAZIONE RICORSIVA: Esempi di problemi ricorsivi:

FUNZIONI che operano su LISTE

Transcript:

Olimpiadi di Informatica 2009 Giornate preparatorie Dipartimento di Informatica Università di Torino Elio Giovannetti marzo 2009 Lino il giornalaio. 03/19/09 1

Caratterizzazione ricorsiva Siano val[0], val[1],..., val[n-1] i rispettivi valori degli n tipi di monete a disposizione. Il numero di modi nmodi(s, i) in cui si può realizzare la somma S con monete di valori da val[0] a val[i] inclusi (non necessariamente usando tutti i valori da val[0] a val[i]) è dato da: il numero di modi in cui si può realizzare la somma S con monete di valori da val[0] a val[i-1], cioè senza usare monete di valore val[i] + il numero di di modi in cui si può realizzare la somma S con monete di valori da val[0] a val[i] che usano almeno una moneta di valore val[i]. 19/03/09 23.32 2

Ma si ha: il numero di modi in cui si può realizzare la somma S con monete di valori da val[0] a val[i-1] è nmodi(s, i-1) ; il numero di di modi in cui si può realizzare la somma S con monete di valori da val[0] a val[i] che usano almeno una moneta di valore val[i] si ottiene nel modo seguente: si sottrae dalla somma S una moneta val[i], e poi si conta in quanti modi si può ottenere tale somma S val[i] usando monete di valori da val[0] a val[i]; quindi è nmodi(s val[i], i). Nota bene: se in tale conto usassimo solo monete di valori da val[0] a val[i-1] otterremmo solo il numero di modi di realizzare S usando una sola moneta val[i]. Quindi: nmodi(s, i) = nmodi(s, i-1) + nmodi(s val[i], i) ;

Base della ricorsione La somma 0 può essere realizzata in un modo solo, quali che siano le monete permesse (ed è formata da 0 monete): nmodi(0, i) = 1 per qualunque i. Una somma S diversa da 0 non può essere realizzata senza monete, quindi: nmodi(s, -1) = 0 per qualunque S 0 (nota che senza monete vuol dire i = -1, perché per i = 0 si ha il primo tipo di moneta, di valore val[0]); più in generale potremmo scrivere nmodi(s, i) = 0 per i < 0 (ed S 0). Una somma S negativa non può essere realizzata, quali che siano le monete permesse; quindi: nmodi(s, i) = 0 per qualunque i, se S < 0. Nota che questo caso base si verifica quando si sottrae una moneta di valore maggiore della somma rimasta.

La caratterizzazione ricorsiva può essere tradotta direttamente in una funzione ricorsiva C o Pascal long nmodi(int s, int i) { if(s == 0) return 1; if(s < 0) return 0; if(i < 0) return 0; return nmodi(s, i-1) + nmodi(s-val[i], i); } Nota Bene: è essenziale che il test s == 0 venga fatto prima del test i < 0, affinché per s == 0 la funzione restituisca 1 anche se i < 0.

Versione iterativa La soluzione ricorsiva precedente è inefficiente, perché ricalcola molte volte gli stessi risultati parziali. Una soluzione più efficiente si ottiene con una realizzazione iterativa che memorizza in un array i risultati parziali via via ottenuti, che possono così essere riutilizzati senza bisogno di ricalcolarli (tecnica della programmazione dinamica).

Siano Versione iterativa N il numero dei differenti valori di monete, R la somma da realizzare con le monete. Si tiene un array num indiciato da 0 fino al valore R, e si effettuano N successive scansioni dell array: al termine dell i-esima scansione ogni elementi num[s] deve contenere il num. di modi in cui si può realizzare la somma parziale s con monete di valori da val[0] a val[i]. Al termine delle N scansioni, nell ultimo elemento dell array ci sarà il risultato. Lo schema è quindi: for (int i = 0; i < N; i++) {... for (int s =...; s <= R; s++)... }

All inizio dell i-esima iterazione del ciclo esterno, num[s] contiene il n. di modi in cui si può realizzare la somma s con monete da val[0] a val[i-1] (incluse). Vogliamo aggiornare ciascun num[s] in modo che contenga il n. di modi della somma s con monete fino a val[i] (inclusa). Notiamo che per s < val[i] non si possono usare monete di valore val[i], e quindi il n. di modi num[s] rimane lo stesso. I due for annidati devono avere quindi la forma: for (int i = 0; i < N; i++) { int valore = val[i]; for (int s = valore; s <= R; s++)... }

num: Situazione al passo generico, con indici i ed s. s-v Per s < s l array è già stato aggiornato, quindi è num[s ] = nmodi(s, i); cioè num[s-v] = nmodi(s-v, i); Per s s l array deve ancora essere aggiornato, quindi è num[s ] = nmodi(s, i-1); e in particolare è num[s] = nmodi(s, i-1); Vogliamo fare in modo che num[s] diventi nmodi(s, i); ma sappiamo che è nmodi(s, i) = nmodi(s, i-1) + nmodi(s val[i], i) ; quindi basterà fare: num[s] = num[s] + num[s-val[i]]; s

Inizializzazione La somma 0 può essere realizzata in un solo modo, quindi porremo inizialmente num[0] = 1, e tutti gli altri elementi uguali a zero: num[0] = 1; for(int s = 1; s <= R; s++) num[s] = 0; Nota: in C++ se l array num è dichiarato globalmente, cioè fuori dal main, esso viene inizializzato automaticamente a 0, e quindi il ciclo for scritto qui sopra non è necessario.

Conclusione int main() { fin >> N >> R; for(int i = 0; i < N; i++) fin >> val[i]; // fine parte di input } num[0] = 1; for(int s = 1; s <= R; s++) num[s] = 0; for (int i = 0; i < N; i++) { int valore = val[i]; for (int s = valore; s <= R; s++) num[s] += num[s-valore]; } cout << num[r] << endl; fout << num[r];