Advertisement
cmiN

fii-12

Jul 26th, 2012
408
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.79 KB | None | 0 0
  1. /*
  2.  * Problema 3 (III) la testul de admitere din 2012 la FII (UAIC)
  3.  *
  4.  * La punctul a) se raspundea cu solutia naiva: pentru fiecare
  5.  * x0 si pentru fiecare x1 se luau valori, apoi se verifica
  6.  * suma pentru a stabili daca perechea de numere constitue solutie.
  7.  *
  8.  * La b) se poate implementa destul de usor doar respectand ideea
  9.  * sumei precizate de cerinta. Alegerea x-ului se face in functie
  10.  * de semnul coeficientului si de conotatia functiei.
  11.  *
  12.  * c) poate baga putin in ceata mintea programatorului avand impresia
  13.  * ca folosirea respectivelor functii poate duce la o complexitate
  14.  * polinomiala (sau cu mult mai mica decat cea exponentiala) insa
  15.  * ele reprezinta o euristica catre verificarea la fiecare pas daca
  16.  * x-ul ales poate reprezenta un candidat bun pentru ecuatie.
  17.  */
  18.  
  19.  
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22.  
  23.  
  24. typedef struct {
  25.     /**
  26.      * Structura pentru stabilirea minimului
  27.      * si maximului pornind de la un index.
  28.      *
  29.      * De obicei utilizata intr-un tablou pentru
  30.      * a nu calcula de fiecare data cand este nevoie.
  31.      */
  32.     int lo; // minim
  33.     int hi; // maxim
  34. } Extr;
  35.  
  36.  
  37. int min(int n, int a[], int b, int inf, int sup, int k)
  38. {
  39.     /**
  40.      * Functia de calculare a minimului.
  41.      * Nu inteleg totusi la ce-mi trebuie b,
  42.      * probabil gresesc pe undeva.
  43.      */
  44.     int sum = 0;
  45.     /* calculam si adunam liniar de la k la n minimul
  46.      * fiecarui element ce duc implicit la minimul sumei
  47.      */
  48.     int i;
  49.     for (i = k; i < n; ++i) {
  50.         int coef = a[i];
  51.         if (!coef) continue; // nu avem ce aduna
  52.         else if (coef > 0) {
  53.             /* pozitiv, deci numarul cel mai mic
  54.              * va fi dat de capatul inferior
  55.              */
  56.             sum += coef * inf;
  57.         } else {
  58.             // analog pentru capatul superior
  59.             sum += coef * sup;
  60.         }
  61.     }
  62.     /* returnam cea mai mica suma posibila pentru orice x
  63.      * pornind de la k la n
  64.      */
  65.     return sum;
  66. }
  67.  
  68.  
  69. int max(int n, int a[], int b, int inf, int sup, int k)
  70. {
  71.     /**
  72.      * Functia de calculare a maximului.
  73.      * Nu inteleg totusi la ce-mi trebuie b,
  74.      * probabil gresesc pe undeva.
  75.      */
  76.     int sum = 0;
  77.     /* calculam si adunam liniar de la k la n maximul
  78.      * fiecarui element ce duc implicit la maximul sumei
  79.      */
  80.     int i;
  81.     for (i = k; i < n; ++i) {
  82.         int coef = a[i];
  83.         if (!coef) continue; // nu avem ce aduna
  84.         else if (coef > 0) {
  85.             /* pozitiv, deci numarul cel mai mare
  86.              * va fi dat de capatul superior
  87.              */
  88.             sum += coef * sup;
  89.         } else {
  90.             // analog pentru capatul inferior
  91.             sum += coef * inf;
  92.         }
  93.     }
  94.     /* returnam cea mai mare suma posibila pentru orice x
  95.      * pornind de la k la n
  96.      */
  97.     return sum;
  98. }
  99.  
  100.  
  101. int* solutie(int n, int a[], int b, int inf, int sup)
  102. {
  103.     /**
  104.      * Functie ce calculeaza naiv solutia (adica pentru fiecare
  105.      * coeficient alegem pe rand fiecare x, verificand cu functiile
  106.      * min si max daca alegerea facuta poate ajuta la formarea solutiei,
  107.      * si verificam la final daca are loc egalitatea).
  108.      *
  109.      * Aceasta returneaza un pointer la primul element din tablou,
  110.      * tablou creat dinamic, avand in cazul unei solutii o valoare
  111.      * diferita de NULL.
  112.      */
  113.     /* alocam dinamic memorie, nu mai are rost sa verificam
  114.      * daca s-a alocat cu succes si declaram pointerul static
  115.      * pentru ca folosim aceeasi functie in mod recursiv
  116.      * astfel protejand integritatea continutului
  117.      */
  118.     static int* vec = NULL; // initial e 0
  119.     /* la urmatorul apel vec va ramane neschimbat
  120.      * nu va fi iar initializat cu NULL
  121.      */
  122.     // in sfarsit alocam memoria aia :))
  123.     if (!vec) vec = (int*)malloc((size_t)n * sizeof(int));
  124.     // similar procedam si pentru pozitie curenta
  125.     static int pos = 0;
  126.     // la fel si pentru minime si maxime
  127.     static Extr* extr = NULL;
  128.     if (!extr) {
  129.         // alocam memoria si atribuim pointerului valoarea
  130.         extr = (Extr*)malloc((size_t)n * sizeof(Extr));
  131.         // generam sumele
  132.         int i;
  133.         for (i = 0; i < n; ++i) {
  134.             extr[i].lo = min(n, a, b, inf, sup, i);
  135.             extr[i].hi = max(n, a, b, inf, sup, i);
  136.         }
  137.         // acest calcul se face o singura data
  138.     }
  139.     static int sum = 0; // tinem cont de suma pana la pasul curent
  140.     // si acum ceea ce functia trebuie sa faca de fiecare data
  141.     // avem de generat pentru fiecare x
  142.     int x;
  143.     for (x = inf; x <= sup; ++x) {
  144.         /* acum pentru acest x
  145.         * calculam noul minim si maxim
  146.         * si vedem daca rezultatul
  147.         * final se afla intre ele
  148.         */
  149.         // suma curenta plus noul x * coeficientul sau
  150.         int newSum = sum + x * a[pos];
  151.         vec[pos] = x;
  152.         if (pos == n - 1) {
  153.             // am ajuns la final deci verificam ecuatia
  154.             if (newSum == b) {
  155.                 // nu ne mai trebuiesc extremitatile
  156.                 free(extr);
  157.                 return vec; // avem solutie
  158.             }
  159.         } else {
  160.             // verificam daca b se incadreaza
  161.             if (b >= (newSum + extr[pos + 1].lo) &&
  162.                 b <= (newSum + extr[pos + 1].hi)) {
  163.                 /* actualizam suma dar pastram si
  164.                  * vechea valoare pentru intoarcere
  165.                  * la fel si pentru pozitie
  166.                  */
  167.                 int tmpSum = sum;
  168.                 sum = newSum;
  169.                 ++pos;
  170.                 int* ret = solutie(n, a, b, inf, sup);
  171.                 if (ret) return ret; /* transmitem solutia mai
  172.                                       * departe pentru ca o avem
  173.                                       */
  174.                 --pos;
  175.                 sum = tmpSum;
  176.             }
  177.         }
  178.     }
  179.     if (!pos) {
  180.         /* nu avem solutie si suntem pe prima pozitie
  181.          * deci e clar ca nu avem nicio solutie,
  182.          * asa ca eliberam
  183.          */
  184.         free(vec);
  185.         free(extr);
  186.     }
  187.     return NULL; // nu avem solutie
  188. }
  189.  
  190.  
  191. int main()
  192. {
  193.     int n, b, inf, sup;
  194.     printf("n b inf sup: ");
  195.     scanf("%d %d %d %d", &n, &b, &inf, &sup);
  196.     // alocam memorie pentru tabloul a
  197.     int* a = (int*)malloc((size_t)n * sizeof(int));
  198.     printf("Cei %d coeficienti: ", n);
  199.     int i;
  200.     for (i = 0; i < n; ++i) scanf("%d", &a[i]);
  201.     int* ret = solutie(n, a, b, inf, sup); // citim tabloul
  202.     free(a);
  203.     if (ret) { // difera de NULL deci avem solutie
  204.         // afisam
  205.         puts("Solutia este...");
  206.         int i;
  207.         for (i = 0; i < n; ++i) printf("x%d: %d\n", i, ret[i]);
  208.         // eliberam memoria
  209.         free(ret);
  210.     } else puts("Nu exista solutie.");
  211.     fflush(stdout); // eliberam bufferul (in caz de nu apar rezultatele pe ecran)
  212.     return 0;
  213. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement