// Laboratorio 6 - Esercizio 2 // Matteo Schiff - s295565 #include #include int fZ(int z, int r, int t, int s, int len); int fR(int z, int r, int t, int s, int len); int fS(int z, int r, int t, int s, int len); int fT(int z, int r, int t, int s, int len); enum Pietra{zaffiro, rubino, topazio, smeraldo}; int *cache; int mz, mr, mt, ms; // Funzioni helper per semplificare la memorizzazione // NOTA se `getCache` restituisce 0 vuol dire che la collana non è ancora stata analizzata int getCache(int p, int z, int r, int t, int s) { return *(cache + p*mz*mr*mt*ms + z*mr*mt*ms + r*mt*ms + t*ms + s); } void saveCache(int p, int z, int r, int t, int s, int val) { *(cache + p*mz*mr*mt*ms + z*mr*mt*ms + r*mt*ms + t*ms + s) = val; } int fZ(int z, int r, int t, int s, int len) { if (len != 0 && getCache(zaffiro, z,r,t,s) != 0) { return getCache(zaffiro,z,r,t,s); } int x = -1; int m; if (z > 0) { m = fZ(z-1,r,t,s,len +1); if (m > x) x = m; } if (r > 0) { m = fR(z,r-1,t,s,len +1); if (m > x) x = m; } // se non è possibile più aggiungere pietre, ho raggiunto la lunghezza massima ottenibile dal ramo if (x == -1) { saveCache(zaffiro,z,r,t,s,len); return len; } // se no restituisco il massimo fin'ora saveCache(zaffiro,z,r,t,s,x); return x; } int fR(int z, int r, int t, int s, int len) { if (len != 0 && getCache(rubino, z,r,t,s) != 0) { return getCache(rubino,z,r,t,s); } int x = -1; int m; if (s > 0) { m = fS(z,r,t,s-1,len +1); if (m > x) x = m; } if (t > 0) { m = fT(z,r,t-1,s,len +1); if (m > x) x = m; } // se non è possibile più aggiungere pietre, ho raggiunto la lunghezza massima ottenibile dal ramo if (x == -1) { saveCache(rubino,z,r,t,s,len); return len; } // se no restituisco il massimo fin'ora saveCache(rubino,z,r,t,s,x); return x; } int fT(int z, int r, int t, int s, int len) { if (len != 0 && getCache(topazio, z,r,t,s) != 0) { return getCache(topazio,z,r,t,s); } int x = -1; int m; if (z > 0) { m = fZ(z-1,r,t,s,len +1); if (m > x) x = m; } if (r > 0) { m = fR(z,r-1,t,s,len +1); if (m > x) x = m; } // se non è possibile più aggiungere pietre, ho raggiunto la lunghezza massima ottenibile dal ramo if (x == -1) { saveCache(topazio,z,r,t,s,len); return len; } // se no restituisco il massimo fin'ora saveCache(topazio,z,r,t,s,x); return x; } int fS(int z, int r, int t, int s, int len) { if (len != 0 && getCache(smeraldo, z,r,t,s) != 0) { return getCache(smeraldo,z,r,t,s); } int x = -1; int m; if (s > 0) { m = fS(z,r,t,s-1,len +1); if (m > x) x = m; } if (t > 0) { m = fT(z,r,t-1,s,len +1); if (m > x) x = m; } // se non è possibile più aggiungere pietre, ho raggiunto la lunghezza massima ottenibile dal ramo if (x == -1) { saveCache(smeraldo,z,r,t,s,len); return len; } // se no restituisco il massimo fin'ora saveCache(smeraldo,z,r,t,s,x); return x; } void solveCase(int z, int r, int t, int s) { mz = z+1; mr = r+1; mt = t+1; ms = s+1; cache = calloc(4*mz*mr*mt*ms, sizeof(int)); int max = z+r+t+s; int res = -1, x; printf("zaffiri = %d, rubini = %d, topazi = %d, smeraldi = %d; numero pietre = %d\n", z,r,t,s,max); x = fZ(z-1,r,t,s,1); if (x > res) res = x; x = fR(z,r-1,t,s,1); if (x > res) res = x; x = fS(z,r,t,s-1,1); if (x > res) res = x; x = fT(z,r,t-1,s,1); if (x > res) res = x; free(cache); printf("Collana massima di lunghezza %d\n", res); fflush(stdout); } int main() { int z, r, t, s, N = 0; FILE *fp; if ((fp = fopen("hard_test_set.txt", "r")) == NULL) { puts("Impossibile aprire il file"); return 1; } fscanf(fp, "%d", &N); for (int i = 0; i < N; i++) { fscanf(fp, " %d %d %d %d", &z, &r, &t, &s); printf("Test case %d\n", i+1); solveCase(z,r,t,s); } fclose(fp); }