#include #include #include #include "Elementi.h" #define MAX_ELEM 5 #define MAX_DIAG 3 typedef struct params { bool acrobNecessaria; bool acrobAvantiNecessaria; bool acrobIndietroNecessaria; } Requirements; Elemento *leggiFile(char *filename, int *N) { FILE *fin; if ((fin = fopen(filename, "r")) == NULL) { puts("Impossibile aprire il file"); return NULL; } fscanf(fin, "%d", N); Elemento *lista = malloc(*N * sizeof(Elemento)); for (int i = 0; i < *N; i++) { lista[i] = leggiElemento(fin); } fclose(fin); return lista; } float calcElementValue(Elemento e, Requirements reqs, bool acrobInSeqNecessaria) { float value = (e.valore / e.diff); if (e.tipo == AVANTI && reqs.acrobAvantiNecessaria) { value += 1; } if (e.tipo == INDIETRO && reqs.acrobIndietroNecessaria) { value += 1; } if (e.tipo > 0 && reqs.acrobNecessaria) { value += 1; } if (e.tipo > 0 && acrobInSeqNecessaria) { value += 1; } return value; } // variabili passate come contesto alla funzione di confronto chiamata da qsort Requirements context; bool acrobInSeqNecessariaSort; int greedyChoice(const void *a, const void *b) { Elemento x = *(Elemento *)a; Elemento y = *(Elemento *)b; float va = calcElementValue(x, context, acrobInSeqNecessariaSort); float vb = calcElementValue(y, context, acrobInSeqNecessariaSort); return vb > va; } void sortAccettabili(Elemento *accettabili, int N, Requirements *reqs, bool acrobInSeqNecessaria) { context = *reqs; acrobInSeqNecessariaSort = acrobInSeqNecessaria; qsort(accettabili, N, sizeof(Elemento), greedyChoice); } int getAccettabili(Elemento *accettabili, Elemento *elementi, int N, int DD, int DP, Elemento *soluzione, int posizioneAssoluta, int posInDiag, int currKp, int diffDiags[MAX_DIAG], int diffTot) { int N_accettabili = 0; for (int i = 0; i < N; i++) { if (diffDiags[currKp] + elementi[i].diff > DD || diffTot + elementi[i].diff > DP) continue; if (posInDiag == 0 && elementi[i].dirIngresso != FRONTE) continue; if (posInDiag > 0 && elementi[i].dirIngresso != soluzione[posizioneAssoluta-1].dirUscita) continue; if (posInDiag == 0 && elementi[i].reqPreced) continue; accettabili[N_accettabili++] = elementi[i]; } return N_accettabili; } void stampaSoluzione(Elemento *sol, int N, int *kp) { int i, j, diagonaleBonus = -1; float tot = 0, parz; // Ricerca possibile diagonale con elemento bonus for (i = 0; i < MAX_DIAG && diagonaleBonus == -1; i++) { for (j = 0; j < MAX_ELEM && diagonaleBonus == -1; j++) { if ((kp[j + MAX_ELEM * i] == -1 || j == MAX_ELEM - 1) && sol[j + MAX_ELEM * i - 1].diff >= 8) { diagonaleBonus = i; } } } // Scambio diagonale bonus, se trovata, con l'ultima diagonale if (diagonaleBonus != -1 && diagonaleBonus != MAX_DIAG - 1) { for (i = 0; i < N; i++) { if (kp[i] == diagonaleBonus) kp[i] = MAX_DIAG; if (kp[i] == MAX_DIAG - 1) kp[i] = diagonaleBonus; } for (i = 0; i < N; i++) { if (kp[i] == MAX_DIAG) kp[i] = MAX_DIAG - 1; } diagonaleBonus = MAX_DIAG - 1; } for (j = 0; j < MAX_DIAG; j++) { parz = 0; for (i = 0; i < N; i++) { if (kp[i] == j) { parz += sol[i].valore; } } printf("DIAG #%d > %.3f", j+1, parz); if (j == diagonaleBonus) printf(" * 1.5 (BONUS)"); printf("\n"); if (j == diagonaleBonus) { parz = parz * 1.5; } tot += parz; for (i = 0; i < N; i++) { if (kp[i] == j) { printf("%s ", sol[i].nome); } } printf("\n"); } printf("TOT = %.3f\n", tot); } void trovaProgrammaGreedy(Elemento *elementi, int N, int DD, int DP) { int diffDiags[MAX_DIAG] = {0}; int tmp, minDiffAvanti = DD, minDiffIndietro = DD; Requirements reqs[MAX_DIAG]; bool found; bool contieneElemFinale[MAX_DIAG]; bool acrobInSeqNecessaria = true; for (int i = 0; i < N; i++) { if (elementi[i].diff < minDiffAvanti && elementi[i].tipo == AVANTI) minDiffAvanti = elementi[i].diff; if (elementi[i].diff < minDiffIndietro && elementi[i].tipo == INDIETRO) minDiffIndietro = elementi[i].diff; } for (int i = 0; i < MAX_DIAG; i++) { contieneElemFinale[i] = false; reqs[i].acrobAvantiNecessaria = reqs[i].acrobIndietroNecessaria = reqs[i].acrobNecessaria = true; } int *kp = (int *) malloc(MAX_DIAG * MAX_ELEM * sizeof(int)); for (int i = 0; i < MAX_DIAG * MAX_ELEM; i++) kp[i] = -1; Elemento *soluzione = (Elemento *) malloc(MAX_DIAG * MAX_ELEM * sizeof(Elemento)); Elemento *accettabili = (Elemento *) malloc(N * sizeof(Elemento)); int diffTot = 0; for (int numElem = 0; numElem < MAX_ELEM; numElem++) { for (int numDiag = 0; numDiag < MAX_DIAG; numDiag++) { int posizioneAssoluta = numElem + numDiag * MAX_ELEM; if (!contieneElemFinale[numDiag]) { int numAcc = getAccettabili(accettabili, elementi, N, DD, DP, soluzione, posizioneAssoluta, numElem, numDiag, diffDiags, diffTot); if (numAcc > 0) { // Ordinamento descrescente delle scelte possibili sortAccettabili(accettabili, numAcc, &reqs[numDiag], acrobInSeqNecessaria); if (reqs[numDiag].acrobAvantiNecessaria != reqs[numDiag].acrobIndietroNecessaria) { found = false; if (reqs[numDiag].acrobAvantiNecessaria) { for (int i = 0; i < numAcc && !found; i++) { // Scelgo la prima diagonale che soddisfa la condizione if (accettabili[i].tipo == AVANTI) { found = true; soluzione[posizioneAssoluta] = accettabili[i]; kp[posizioneAssoluta] = numDiag; } } if (!found) { for (int i = 0; i < numAcc && !found; i++) { if (accettabili[i].dirIngresso != accettabili[i].dirUscita && diffDiags[numDiag] + accettabili[i].diff + minDiffAvanti <= DD && !accettabili[i].finale) { soluzione[posizioneAssoluta] = accettabili[i]; kp[posizioneAssoluta] = numDiag; found = true; for (tmp = 0; tmp < MAX_DIAG; tmp++) reqs[tmp].acrobAvantiNecessaria = false; reqs[numDiag].acrobAvantiNecessaria = true; } } if (!found) { // Effettuo scelta localmente ottima soluzione[posizioneAssoluta] = accettabili[0]; kp[posizioneAssoluta] = numDiag; } } } if (reqs[numDiag].acrobIndietroNecessaria) { for (int i = 0; i < numAcc && !found; i++) { if (accettabili[i].tipo == INDIETRO) { found = true; // Effettuo scelta localmente ottima soluzione[posizioneAssoluta] = accettabili[i]; kp[posizioneAssoluta] = numDiag; } } if (!found) { found = false; for (int i = 0; i < numAcc && !found; i++) { if (accettabili[i].dirIngresso != accettabili[i].dirUscita && diffDiags[numDiag] + accettabili[i].diff + minDiffIndietro <= DD && !accettabili[i].finale) { soluzione[posizioneAssoluta] = accettabili[i]; kp[posizioneAssoluta] = numDiag; for (tmp = 0; tmp < MAX_DIAG; tmp++) reqs[tmp].acrobIndietroNecessaria = false; reqs[numDiag].acrobIndietroNecessaria = true; found = true; } } if (!found) { // Effettuo scelta localmente ottima soluzione[posizioneAssoluta] = accettabili[0]; kp[posizioneAssoluta] = numDiag; } } } } else { // Effettuo scelta localmente ottima soluzione[posizioneAssoluta] = accettabili[0]; kp[posizioneAssoluta] = numDiag; } // Aggiornamento difficoltà diffDiags[numDiag] += soluzione[posizioneAssoluta].diff; diffTot += soluzione[posizioneAssoluta].diff; // Aggiornamento parametri funzione obiettivo if (soluzione[posizioneAssoluta].tipo == AVANTI) { for (int i = 0; i < MAX_DIAG; i++) reqs[i].acrobAvantiNecessaria = false; reqs[numDiag].acrobIndietroNecessaria = false; } if (soluzione[posizioneAssoluta].tipo == INDIETRO) { for (int i = 0; i < MAX_DIAG; i++) reqs[i].acrobIndietroNecessaria = false; reqs[numDiag].acrobAvantiNecessaria = false; } if (numElem > 0 && soluzione[posizioneAssoluta].tipo > 0 && soluzione[posizioneAssoluta-1].tipo > 0) { for (int i = 0; i < MAX_DIAG; i++) acrobInSeqNecessaria = false; } if (soluzione[posizioneAssoluta].finale) { // Blocco l'inserimento di elementi nella diagonale contieneElemFinale[numDiag] = true; } } } } } stampaSoluzione(soluzione, MAX_DIAG * MAX_ELEM, kp); free(accettabili); free(soluzione); free(kp); return; } int main() { int N = 0, DP, DD;; Elemento *l = leggiFile("elementi.txt", &N); printf("Inserisci DD e DP: "); scanf("%d %d", &DD, &DP); trovaProgrammaGreedy(l, N, DD, DP); free(l); return 0; }