[C++] Matrice : controllo sulle colonne.
Salve a tutti. Avrei il seguente problema: Avendo una matrice quadrata devo calcolarmi l'elemento della matrice che ha come riga il valore dell'elemento minimo, e come colonna il valore dell'elemento massimo. Ora come supporto il libro mi dice di usare una funzione calc_ind_min che ha come parametri di ingresso un vettore e un riempimento e mi ritorna l'indice del valore minimo. Ora non so gestire la funzione che mi trova l'elemento che soddisfa quelle condizioni. Come faccio avendo un indice di riga a lavorare sulle colonne?
Risposte
A mio avviso ti conviene cercare massimo e minimo in un unico scan. Supponi di avere una matrice
\[\begin{pmatrix} 1 & 2 & 3 & 4 \\
5 & 6 & 7 & 8 \\
9 & 10 & 11 & 12
\end{pmatrix}\]
Supponendo sia una matrice statica o allocata dinamicamente in modo sensato quest'ultima è memorizzata in memoria come \begin{pmatrix} 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10 & 11 & 12 \end{pmatrix}
Quello che tu devi fare è fare un ciclo su questo array e trovare l'indice minimo e massimo. Tenendo conto che l'elemento \(\displaystyle (i,j) \) di una matrice \(\displaystyle m\times n \) ha indice in memoria \(\displaystyle i\times n + j \) una volta trova l'indice k ti basta fare \(\displaystyle i = k/n \) e \(\displaystyle j = k\%n \). Non so se mi sono spiegato.
Cos'è un riempimento?
\[\begin{pmatrix} 1 & 2 & 3 & 4 \\
5 & 6 & 7 & 8 \\
9 & 10 & 11 & 12
\end{pmatrix}\]
Supponendo sia una matrice statica o allocata dinamicamente in modo sensato quest'ultima è memorizzata in memoria come \begin{pmatrix} 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10 & 11 & 12 \end{pmatrix}
Quello che tu devi fare è fare un ciclo su questo array e trovare l'indice minimo e massimo. Tenendo conto che l'elemento \(\displaystyle (i,j) \) di una matrice \(\displaystyle m\times n \) ha indice in memoria \(\displaystyle i\times n + j \) una volta trova l'indice k ti basta fare \(\displaystyle i = k/n \) e \(\displaystyle j = k\%n \). Non so se mi sono spiegato.
Cos'è un riempimento?
Il numero di elementi del vettore(cardinalità). Il problema è che mi dice di usare quella funzione per forza...
Se ho capito bene il tuo problema, devi trovare degli indici \((i, j)\) per cui valgano le seguenti condizioni:
\[ A_{ij} \leq A_{ik}, \quad A_{ij} \geq A_{sj} \quad \forall \, k \in \{1 \dotsc n\} , s \in \{ 1 \dotsc m \}. \]
È corretto?
Che cosa intendi come "riempimento"? Se il problema è quello sopra esposto, allora utilizzerei il seguente "algoritmo". Per ogni riga trova il valore minimo usando la tua funzione. La funzione ti restituisce a questo punto l'indice della colonna da prendere in considerazione. A questo punto devi iterare su tutti gli elementi della colonna e vedere se l'elemento sulla riga iniziale è il massimo. A seconda di cosa intendi con riempimento, questa operazione potrebbe essere effettuata o meno con la tua funzione. Se per esempio la tua funzione fosse definita nel modo seguente (sto usando valore interi per la matrice ma basta sostituire il tipo con quello di cui hai bisogno oppure usare dei template):
Allora la potresti utilizzare. Stai infatti considerando vettori in cui gli elementi potrebbero essere distanziati di un certo numero di elementi (in pratica step dovrebbe probabilmente essere il numero di byte, ma così è più semplice) e può quindi essere usato anche per le colonne. In memoria gli elementi di una colonna sono infatti distanziati da \(n\) elementi (il numero di colonne).
EDIT: Ovviamente non lo puoi usare.. perché nelle colonne stai cercando il massimo e non il minimo..
\[ A_{ij} \leq A_{ik}, \quad A_{ij} \geq A_{sj} \quad \forall \, k \in \{1 \dotsc n\} , s \in \{ 1 \dotsc m \}. \]
È corretto?
Che cosa intendi come "riempimento"? Se il problema è quello sopra esposto, allora utilizzerei il seguente "algoritmo". Per ogni riga trova il valore minimo usando la tua funzione. La funzione ti restituisce a questo punto l'indice della colonna da prendere in considerazione. A questo punto devi iterare su tutti gli elementi della colonna e vedere se l'elemento sulla riga iniziale è il massimo. A seconda di cosa intendi con riempimento, questa operazione potrebbe essere effettuata o meno con la tua funzione. Se per esempio la tua funzione fosse definita nel modo seguente (sto usando valore interi per la matrice ma basta sostituire il tipo con quello di cui hai bisogno oppure usare dei template):
int calc_ind_min(int *v, int len, int step) { if (len < 1) { return -1; } int min = v[0]; int min_idx = 0; for (int i = 1; i < len; ++i) { const int w = v[i*step]; if (w < min) { min = w; min_idx = i; } } return min_idx; }
Allora la potresti utilizzare. Stai infatti considerando vettori in cui gli elementi potrebbero essere distanziati di un certo numero di elementi (in pratica step dovrebbe probabilmente essere il numero di byte, ma così è più semplice) e può quindi essere usato anche per le colonne. In memoria gli elementi di una colonna sono infatti distanziati da \(n\) elementi (il numero di colonne).
EDIT: Ovviamente non lo puoi usare.. perché nelle colonne stai cercando il massimo e non il minimo..
Si fino a qui ci sono. Mi creo questa funzione che mi restituisce l'indice del valore minimo. La mia difficoltà è quando devo ricercare il massimo conoscendo l'indice del minimo, non riesco ad iterare solo su quella colonna. Come faccio a fissare una riga e fare operazioni su quella colonna?
Tieni fisso l'indice della colonna (quello che ti ha restituito la funzione) e cambia quello della riga.
Non riesco a farlo con il doppio for.. come faccio?
Prova a scrivere quello che sei riuscito a fare..
Come faccio a scrivere il codice ?
Inserisci il codice nel testo del post all'interno di tag code ([ code ] .. codice .. [/ code ]) senza spazi intorno a code. Oppure mi chiedevi altro?
Questo ! ora scrivo..
Eccolo:
int calc_ind_min( vettore v,int riemp){ int i,int pos; int min= v[0]; for(i=0;i<riemp;i++) if( v[i]<min){ min=v[i]; pos=i;} return pos; } void calc_elem( matrice mat, int riemp) { int i,j,max=mat[0][0]; for(i=0;i<riemp;i++) for(j=0;j<riemp;j++) if(i== calc_ind_min( mat[i],riemp)) if( mat[i][j]>max) max= mat[i][j]; }
Cos'è matrice? Insomma com'è definita?
typedef int matrice [50][50]; typedef int vettore [50];
In calc_ind_min avresti bisogno di verificare che riemp sia maggiore di zero.. Per quanto riguarda l'altro ciclo è invece tutto sbagliato. Dovrebbe essere qualcosa del genere:
for (int i = 0; i < riemp; i++) { int j = calc_ind_min(mat[i], riemp); int max_idx = i; int max = mat[i][j]; for (int k = 0; k < riemp; k++) { if (max < mat[k][j]) { max = mat[k][j]; max_idx = k; } } if (max_idx == i) { // trovato valore.. } }