#include #include #include #include "Elementi.h" #define MAX_ELEM 5 #define MAX_DIAG 3 typedef struct params { bool acrobNecessaria; } Requirements; typedef struct gparams { bool acrobAvantiNecessaria; bool acrobIndietroNecessaria; bool acrobInSeqNecessaria; } GlobalRequirements; 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, GlobalRequirements greqs) { float value = (e.valore / e.diff); if (e.tipo == AVANTI && greqs.acrobAvantiNecessaria) { value += 1; } if (e.tipo == INDIETRO && greqs.acrobIndietroNecessaria) { value += 1; } if (e.tipo > 0 && reqs.acrobNecessaria) { value += 1; } if (e.tipo > 0 && greqs.acrobInSeqNecessaria) { value += 1; } return value; } // variabili passate come contesto alla funzione di confronto chiamata da qsort Requirements context; GlobalRequirements gcontext; int greedyChoice(const void *a, const void *b) { Elemento x = *(Elemento *)a; Elemento y = *(Elemento *)b; float va = calcElementValue(x, context, gcontext); float vb = calcElementValue(y, context, gcontext); return vb > va; } void swap(int *a, int *b) { int c = *a; *a = *b; *b = c; } void swapE(Elemento *a, Elemento *b) { Elemento c = *a; *a = *b; *b = c; } void sortAccettabili(Elemento *accettabili, int N, Requirements *reqs, GlobalRequirements *greqs) { context = *reqs; gcontext = *greqs; 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 *soluzione, int *diagSize) { float totPoints = 0, diagPoints; for (int i = 0; i < MAX_DIAG; i++) { diagPoints = 0; for (int j = 0; j < diagSize[i]; j++) { diagPoints += soluzione[i * MAX_ELEM + j].valore; } printf("DIAG #%d > %.3f", i + 1, diagPoints); if (i == MAX_DIAG - 1 && soluzione[diagSize[i] + i * MAX_ELEM - 1].diff >= 8) { printf(" * 1.5 (BONUS)"); diagPoints *= 1.5; } printf("\n"); totPoints += diagPoints; for (int j = 0; j < diagSize[i]; j++) { printf("%s ", soluzione[i * MAX_ELEM + j].nome); } printf("\n"); } printf("TOT = %.3f\n", totPoints); } 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]; GlobalRequirements greqs; bool found; bool contieneElemFinale[MAX_DIAG]; 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].acrobNecessaria = true; } greqs.acrobAvantiNecessaria = greqs.acrobIndietroNecessaria = greqs.acrobInSeqNecessaria = true; int *diagSize = (int *)malloc(MAX_DIAG * sizeof(int)); for (int i = 0; i < MAX_DIAG; i++) diagSize[i] = 0; 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], &greqs); if (greqs.acrobAvantiNecessaria != greqs.acrobIndietroNecessaria || reqs->acrobNecessaria) { found = false; if (greqs.acrobAvantiNecessaria) { for (int i = 0; i < numAcc && !found; i++) { // Scelgo il primo elemento che soddisfa la condizione if (accettabili[i].tipo == AVANTI) { found = true; soluzione[posizioneAssoluta] = accettabili[i]; diagSize[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]; diagSize[numDiag]++; found = true; } } if (!found) { // Effettuo scelta localmente ottima soluzione[posizioneAssoluta] = accettabili[0]; diagSize[numDiag]++; } } } else if (greqs.acrobIndietroNecessaria) { for (int i = 0; i < numAcc && !found; i++) { if (accettabili[i].tipo == INDIETRO) { found = true; // Effettuo scelta localmente ottima soluzione[posizioneAssoluta] = accettabili[i]; diagSize[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]; diagSize[numDiag]++; found = true; } } if (!found) { // Effettuo scelta localmente ottima soluzione[posizioneAssoluta] = accettabili[0]; diagSize[numDiag]++; } } } else { if (!greqs.acrobInSeqNecessaria) { for (int i = 0; i < numAcc && !found; i++) { if (accettabili[i].tipo != TRANSIZIONE && diffDiags[numDiag] + accettabili[i].diff + minDiffAvanti <= DD && !accettabili[i].finale) { soluzione[posizioneAssoluta] = accettabili[i]; diagSize[numDiag]++; found = true; } } if (!found) { // Effettuo scelta localmente ottima soluzione[posizioneAssoluta] = accettabili[0]; diagSize[numDiag]++; } } else { for (int i = 0; i < numAcc && !found; i++) { // Scelgo il primo elemento che soddisfa la condizione if (accettabili[i].tipo != TRANSIZIONE) { found = true; soluzione[posizioneAssoluta] = accettabili[i]; diagSize[numDiag]++; if (!greqs.acrobInSeqNecessaria) { reqs[i].acrobNecessaria = false; } } } } } } else { // Effettuo scelta localmente ottima soluzione[posizioneAssoluta] = accettabili[0]; diagSize[numDiag]++; } // Aggiornamento difficoltà diffDiags[numDiag] += soluzione[posizioneAssoluta].diff; diffTot += soluzione[posizioneAssoluta].diff; // Aggiornamento parametri funzione obiettivo if (soluzione[posizioneAssoluta].tipo == AVANTI) { greqs.acrobAvantiNecessaria = false; } if (soluzione[posizioneAssoluta].tipo == INDIETRO) { greqs.acrobIndietroNecessaria = false; } if (numElem > 0 && soluzione[posizioneAssoluta].tipo > 0 && soluzione[posizioneAssoluta - 1].tipo > 0) { greqs.acrobInSeqNecessaria = false; } if (soluzione[posizioneAssoluta].finale) { // Blocco l'inserimento di elementi nella diagonale contieneElemFinale[numDiag] = true; } } } } } // Cerco la diagonale con l'elemento che permette di ottenere il bonus int bonusDiag = -1; for (int numDiag = 0; numDiag < MAX_DIAG; numDiag++) { if (soluzione[diagSize[numDiag] + numDiag * MAX_ELEM - 1].diff >= 8) bonusDiag = numDiag; } // Sposto se ho trovato un elemento con bonus che non è già in ultima posizione if (bonusDiag != -1 && bonusDiag != MAX_DIAG - 1) { swap(&diagSize[MAX_DIAG - 1], &diagSize[bonusDiag]); for (int i = 0; i < MAX_ELEM; i++) swapE(&soluzione[i + (MAX_DIAG - 1) * MAX_ELEM], &soluzione[i + bonusDiag * MAX_ELEM]); } stampaSoluzione(soluzione, diagSize); free(accettabili); free(soluzione); free(diagSize); 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; }