Diferente pentru probleme-de-acoperire-2 intre reviziile #43 si #53

Nu exista diferente intre titluri.

Diferente intre continut:

(Categoria _Algoritmi_, Autor _Cosmin Negruşeri_)
(toc){width: 30em}*{text-align:center} *Conţinut:*
* 'Problema 1 (TC MagicBoxes)':probleme-de-acoperire-2#problema1
* 'Problema 2 (IOI 2001 Pavement)':probleme-de-acoperire-2#problema2
(toc){width: 37em}*{text-align:center} *Conţinut:*
* 'Problema 1: MagicBoxes (TopCoder)':probleme-de-acoperire-2#problema1
* 'Problema 2: Pavement (IOI 2001)':probleme-de-acoperire-2#problema2
* 'Problema 3 (ACM ICPC 1997)':probleme-de-acoperire-2#problema3
* 'Problema 4 (SGU Hardwood Floor)':probleme-de-acoperire-2#problema4
* 'Problema 5 (TC CaseysArt)':probleme-de-acoperire-2#problema5
* 'Problema 6 (SGU Another chocolate maniac)':probleme-de-acoperire-2#problema6
* 'Problema 7 (CEOI 2002 Bugs)':probleme-de-acoperire-2#problema7
* 'Problema 4: Hardwood Floor (SGU)':probleme-de-acoperire-2#problema4
* 'Problema 5: CaseysArt (TopCoder)':probleme-de-acoperire-2#problema5
* 'Problema 6: Another chocolate maniac (SGU)':probleme-de-acoperire-2#problema6
* 'Problema 7: Bugs (CEOI 2002)':probleme-de-acoperire-2#problema7
* 'Problema 8 (Lot 2001, SGU Domino, IPSC 2004, Algoritmus 2005, IOI 2005)':probleme-de-acoperire-2#problema8
* 'Aplicaţii':probleme-de-acoperire-2#aplicatii
* 'Bibliografie':probleme-de-acoperire-2#bibliografie
Subiectul acestui articol sunt acoperirile in plan, cu o abordare bazată pe tehnici de programare. În "$...secţiunea precedentă$":probleme-de-acoperire-1 am studiat problemele de acoperire care nu necesită cunoştinţe avansate de algoritmi.
h2(#problema1). Problema 1 ('TC MagicBoxes':http://www.topcoder.com/stat?c=problem_statement&pm=932)
h2(#problema1). Problema 1: 'MagicBoxes':http://www.topcoder.com/stat?c=problem_statement&pm=932 (TopCoder)
bq. Să se determine numărul $N$ maxim astfel ca într-un dreptunghi de dimensiuni $L x W (1 ≤ L, W ≤ 30)$ să poată fi dispuse paralel cu axele de coordonate $N$ pătrate de laturi $1, 2, ..., N$ astfel ca oricare două pătrate să nu aibă porţiuni care se suprapun.
Această reprezentare pe biţi este foarte utilă în probleme de acest gen, şi cum avem întregi de $64$ de biţi pe care îi putem folosi, avem o metodă foarte simplă de reprezentare a tablelor de mărime până la $64$.
h2(#problema2). Problema 2 (IOI 2001 Pavement)
h2(#problema2). Problema 2: Pavement (IOI 2001)
bq. Se dă o matrice de dimensiuni $N x M (1 ≤ N ≤ 7 şi 1 ≤ M ≤ 100)$. Unele celule ale acestei matrici sunt distruse şi trebuie acoperite cu piese de forma din $Fig. 1$. Fiecare celulă rămasă neacoperită se consideră o greşeală, iar dacă o piesă cu care am acoperit celule distruse a trebuit să fie tăiată pentru a acoperi numai celule distruse, fiecare pătrăţel din partea nefolosită a piesei este considerată o greşeală. Se cere acoperirea tablei astfel ca numărul de greşeli să fie minimizat. În $Fig. 2$, pentru prima tablă, acoperirea optimă are două greşeli, aşa cum vedem în al doilea desen.
Dacă algoritmul pune trei dominouri pe liniile $4$ şi $5$ aşa cum vedem mai sus, atunci vom trece în starea $(5, 011000)$. La final, vom returna valoarea aflată în $numWays[N + 1][0]$. Complexitatea ca timp a acestei rezolvări este $O(M * 4^N^)$, iar ca spaţiu $O(2^N^)$.
h2(#problema4). Problema 4 ('SGU Hardwood Floor':http://acm.sgu.ru/problem.php?contest=0&problem=131)
h2(#problema4). Problema 4: 'Hardwood Floor':http://acm.sgu.ru/problem.php?contest=0&problem=131 (SGU)
bq. Determinaţi numărul de acoperiri ale unei table de dimensiuni $N x M (1≤ N ≤ 9, 1 ≤ M ≤ 9)$ cu piese de tipul:
În rezolvare putem folosi direct ideea de la problema anterioară.
h2(#problema5). Problema 5 ('TC CaseysArt':http://www.topcoder.com/stat?c=problem_statement&pm=1706)
h2(#problema5). Problema 5: 'CaseysArt':http://www.topcoder.com/stat?c=problem_statement&pm=1706 (TopCoder)
bq. Determinaţi numărul de moduri în care poate fi acoperit un dreptunghi de dimensiuni $N x M (N ≤ 18, M ≤ 15)$ cu piese de forma:
h3. Soluţie:
Din nou, ideea de rezolvare este cea prezentată în 'Problema 2':probleme-de-acoperire-2#problema2. Complexitatea soluţiei este $O(N * 4^M^)$, dar trebuie să fim conştienţi că aceasta este o limită superioară mult mai mare decât complexitatea reală. Să vedem şi implementarea unei asemenea soluţii:
Din nou, ideea de rezolvare este cea prezentată în '$Problema 2$':probleme-de-acoperire-2#problema2. Complexitatea soluţiei este $O(N * 4^M^)$, dar trebuie să fim conştienţi că aceasta este o limită superioară mult mai mare decât complexitatea reală. Să vedem şi implementarea unei asemenea soluţii:
== code(java) |
import java.util.*;
    void checksol() {
        int config = 0, config1 = 0;
        for(int i = 0; i < w; i++) {
            if(sol[i][0] == 0) config |= (1 << i);
            if(sol[i][1] == 1) config1 |= (1 << i);
        for (int i = 0; i < w; i++) {
            if (sol[i][0] == 0) config |= (1 << i);
            if (sol[i][1] == 1) config1 |= (1 << i);
        }
        num[1 ^ step][config1] += num[step][config];
    }
    void doit(int x) {
        if(x == w)
        if (x == w)
            checksol();
        else {
            if(x < w - 1) {
            if (x < w - 1) {
                int i, j, k;
                boolean bool;
                for(k = 0; k < 4; k++) {
                for (k = 0; k < 4; k++) {
                    bool = true;
                    for(i = 0; i < 2; i++) {
                        for(j = 0; j < 2; j++) {
                            if(p[k][i][j] == 1)
                    for (i = 0; i < 2; i++) {
                        for (j = 0; j < 2; j++) {
                            if (p[k][i][j] == 1)
                                bool = bool && (sol[x + i][j] == 0);
                        }
                    }
                    if(bool) {
                        for(i = 0; i < 2; i++) {
                            for(j = 0; j < 2; j++) {
                                if(p[k][i][j] == 1)
                    if (bool) {
                        for (i = 0; i < 2; i++) {
                            for (j = 0; j < 2; j++) {
                                if (p[k][i][j] == 1)
                                    sol[x + i][j] = 1;
                            }
                        }
                        doit(x + 1);
                        for(i = 0; i < 2; i++) {
                            for(j = 0; j < 2; j++) {
                                if(p[k][i][j] == 1)
                        for (i = 0; i < 2; i++) {
                            for (j = 0; j < 2; j++) {
                                if (p[k][i][j] == 1)
                                    sol[x + i][j]=0;
                            }
                        }
        num[0][0] = 1;
        step = 0;
        sol = new int[w][2];
        for(int i = 1; i < l; i++) {
        for (int i = 1; i < l; i++) {
            Arrays.fill(num[1 ^ step], 0);
            doit(0);
            step ^= 1;
În procedura $doit$ punem pe două linii consecutive piese în toate modurile posibile. Această procedură face ca pe prima linie să avem o configuraţie de pătrăţele libere $config$, iar pe a doua o configuraţie de pătrăţele ocupate $config1$. Dacă pătrăţelele reprezentate de $config$ nu au fost ocupate la pasul curent ele trebuie să fi fost ocupate la pasul anterior. Astfel, pentru fiecare pereche de configuraţii $config$ şi $config1$ trebuie să efectuăm operaţia $num[i + 1][config1] += num[i][config]$.
Dacă această rezolvare ar fi fost folosită în timpul concursului ea ar fi ieşit din timp. Pentru optimizarea ei putem face mai multe îmbunătăţiri. Un exemplu ar fi să generăm direct cele două configuraţii de biţi în procedura $backtracking$ şi să nu mai folosim şirul $sol$. O altă idee care ar fi dus la rezolvarea problemei ar fi fost calcularea tuturor rezultatelor posibile în timpul concursului şi trimiterea unei soluţii care returna aceste rezultate precalculate. Această abordare ar fi fost posibilă pentru că numărul de configuraţii iniţiale este mic.
Dacă această rezolvare ar fi fost folosită în timpul concursului, ea ar fi ieşit din timp. Pentru optimizare putem face mai multe îmbunătăţiri. Un exemplu ar fi să generăm direct cele două configuraţii de biţi în procedura $backtracking$ şi să nu mai folosim şirul $sol$. O altă idee care ar fi dus la rezolvarea problemei în timpul concursului ar fi fost calcularea tuturor rezultatelor posibile şi trimiterea unei soluţii care returna aceste rezultate precalculate. Această abordare ar fi fost posibilă pentru că numărul de configuraţii iniţiale este mic.
h2(#problema6). Problema 6 ('SGU Another chocolate maniac':http://acm.sgu.ru/problem.php?contest=0&problem=132)
h2(#problema6). Problema 6: 'Another chocolate maniac':http://acm.sgu.ru/problem.php?contest=0&problem=132 (SGU)
bq. Se dă o tablă de dimensiuni $M x N (1 &le; M &le; 70, 1 &le; N &le; 7)$ cu unele pătrate lipsă. Se cere numărul minim de dominouri ce pot fi plasate pe tablă fară să se sprapună între ele, sau să acopere vreun pătrat ce nu aparţine tablei, astfel ca nici o altă piesă de domino să nu se poată adăuga la configuraţie fără ca aceasta să se suprapună peste una veche. Pentru tabla următoare vedem uşor în a doua figură că soluţia optimă va conţine 4 dominouri.
bq. Se dă o tablă de dimensiuni $M x N (1 &le; M &le; 70, 1 &le; N &le; 7)$ cu unele pătrate lipsă. Se cere numărul minim de dominouri ce pot fi plasate pe tablă fară să se suprapună între ele sau să acopere vreun pătrat ce nu aparţine tablei, astfel ca nici o altă piesă de domino să nu se poată adăuga la configuraţie fără ca aceasta să se suprapună peste una veche. Pentru tabla următoare vedem uşor în a doua figură că soluţia optimă va conţine 4 dominouri.
p=. !probleme-de-acoperire-2?P261.jpg!
Din nou vom folosi $metoda programării dinamice$ îmbinată cu metoda $backtracking$.
Vom umple tabla linie cu linie şi la fiecare pas putem pune dominouri orizontale pe linia curentă şi verticale pe linia curentă şi linia următoare. Trebuie să fim atenţi când trecem de la linia curentă la următoarea să nu lăsăm pe linia curentă loc liber unde poate fi amplasat un domino orizontal, pentru că acest loc nu va putea fi ocupat de piese amplasate mai târziu. Se poate lăsa spaţiu gol pe linia curentă şi linia următoare pentru că o celulă a acestei poziţii va putea fi acoperită la pasul următor. Vedem astfel că dacă linia curentă este linia $i$ atunci avem trei stări posibile pentru ultimele două pătrăţele de pe fiecare coloană: $00$ (celule neocupate), $10$ (penultima celulă ocupată şi ultima goală) $11$ (ambele celule ocupate de dominouri), starea $01$ nu poate exista. În procedura $backtracking$ care generează configuraţiile la care putem ajunge de la o configuraţie dată trebuie să mai avem grijă să nu ocupăm cu un domino o celulă ce nu aparţine tablei. Astfel, pentru a găsi soluţia problemei vom folosi un tablou $min[i][config]$ care va păstra numărul minim de dominouri care trebuie amplasate pe tablă astfel ca pe liniile $1 .. i  1$ să nu poată fi amplasat vreun domino pe celulele rămase goale, $config$ va fi un număr întreg care atunci cănd e transformat în baza $3$ arată configuraţia liniilor $i  1$ şi $i$.
Vom umple tabla linie cu linie şi la fiecare pas putem pune dominouri orizontale pe linia curentă şi verticale pe linia curentă şi linia următoare. Trebuie să fim atenţi când trecem de la linia curentă la următoarea să nu lăsăm pe linia curentă loc liber unde poate fi amplasat un domino orizontal, pentru că acest loc nu va putea fi ocupat de piese amplasate mai târziu. Se poate lăsa spaţiu gol pe linia curentă şi linia următoare pentru că o celulă a acestei poziţii va putea fi acoperită la pasul următor. Vedem astfel că dacă linia curentă este linia $i$ atunci avem trei stări posibile pentru ultimele două pătrăţele de pe fiecare coloană: $00$ (celule neocupate), $10$ (penultima celulă ocupată şi ultima goală), $11$ (ambele celule ocupate de dominouri). Starea $01$ nu poate exista. În procedura $backtracking$ care generează configuraţiile la care putem ajunge de la o configuraţie dată trebuie să mai avem grijă să nu ocupăm cu un domino o celulă ce nu aparţine tablei. Astfel, pentru a găsi soluţia problemei vom folosi un tablou $min[i][config]$ care va păstra numărul minim de dominouri care trebuie amplasate pe tablă astfel ca pe liniile $1, 2, ..., i - 1$ să nu poată fi amplasat vreun domino pe celulele rămase goale, iar $config$ va fi un număr întreg care atunci când e transformat în baza $3$ arată configuraţia liniilor $i - 1$ şi $i$.
La fiecare pas, procedura $backtracking$ alege dacă să pună un domino orizontal, unul vertical sau să treacă mai departe, deci o limită superioară ar fi $O(3^M^)$ operaţii (nu toate configuraţiile vor fi posibile). În tablou avem $N x 3^M^$ stări, deci complexitatea algoritmului este $O(N * 9^M^)$. Menţionăm din nou că aceasta este o limită superioară şi că algoritmul se va comporta mult mai bine în practică.
h2(#problema7). Problema 7 ('CEOI 2002 Bugs':http://acm.pku.edu.cn/JudgeOnline/problem?id=1038)
h2(#problema7). Problema 7: 'Bugs':http://acm.pku.edu.cn/JudgeOnline/problem?id=1038 (CEOI 2002)
bq. Să se acopere o tablă de dimensiuni $M x N (1 &le; M &le; 10, 1 &le; N &le; 150)$ cu un număr maxim de piese de dimensiuni $3 x 2$ şi $2 x 3$. Tabla are unele celule ce trebuie să nu fie acoperite, iar oricare două piese nu se pot suprapune. Pentru tabla de mai jos, numărul maxim de piese cu care se poate acoperi este $3$.
h3. Soluţie:
Evident, putem încerca o soluţie identică cu cea a '$Problemei 1$':probleme-de-acoperire-2#prob1, dar aici limitele sunt puţin mai mari şi avem nevoie de un algoritm mai eficient.
Evident, putem încerca o soluţie identică cu cea a '$Problemei 1$':probleme-de-acoperire-2#problema1, dar aici limitele sunt puţin mai mari şi avem nevoie de un algoritm mai eficient.
Există o rezolvare de complexitate $O(N * M * 3^M^)$ care aşa cum deja v-aţi obişnuit combină metoda $backtracking$ cu metoda $programării dinamice$. Folosim un tablou $max[N][M + 1][3^(M + 1)^]$ care conţine numărul maxim de dale puse pentru o anumită stare. Fiecare element al matricii va avea iniţial $max[i][j][config]$ egal cu $0$. Iterăm rândurile în ordinea $1 .. N$, coloanele în ordinea $1 .. M$ şi configuraţiile în ordine lexicografică. Când vom procesa starea reprezentată de parametrii $(i, j, config)$ vom decide dacă punem una dintre piese cu colţul de stânga sus în $(i, j)$ sau dacă lăsăm celula $(i, j)$ liberă. O stare $(i, j, config)$ se referă la un pătrăţel din matrice şi la o bandă „activă” de pătrăţele ce are lăţimea $2$. Banda conţine celulele $(i1, j + 1), (i1, j + 2)$ pentru $i1 < i$ şi celulele $(i2, j), (i2, j + 1)$ pentru $i &le; i2$. Cifrele în baza $3$ ale parametrului $config$ ne spun starea perechilor de pătrate de pe banda activă: $00$ este reprezentat în $config$ de cifra $0$, $10$ de cifra $1$ şi $11$ de cifra $2$ (configuraţia $01$ nu poate apărea). De exemplu, starea $(4, 3, 1000212)$ va reprezenta configuraţia prezentată în următoarea imagine (ultima cifră corespunde primei perechi de pătrăţele, penultima cifră celei de a doua perechi şamd):
Există o rezolvare de complexitate $O(N * M * 3^M^)$ care, aşa cum deja v-aţi obişnuit, combină metoda $backtracking$ cu metoda $programării dinamice$. Folosim un tablou $max[N][M + 1][3^(M + 1)^]$ care conţine numărul maxim de dale puse pentru o anumită stare. Fiecare element al matricii va fi iniţial egal cu $0$. Iterăm rândurile în ordinea $1 ... N$, coloanele în ordinea $1 ... M$ şi configuraţiile în ordine lexicografică. Când vom procesa starea reprezentată de parametrii $(i, j, config)$ vom decide dacă punem una dintre piese cu colţul din stânga sus în $(i, j)$ sau dacă lăsăm celula $(i, j)$ liberă. O stare $(i, j, config)$ se referă la un pătrăţel din matrice şi la o bandă „activă” de pătrăţele ce are lăţimea $2$. Banda conţine celulele $(i1, j + 1), (i1, j + 2)$ pentru $i1 < i$ şi celulele $(i2, j), (i2, j + 1)$ pentru $i &le; i2$. Cifrele în baza $3$ ale parametrului $config$ ne spun starea perechilor de pătrate de pe banda activă: $00$ este reprezentat în $config$ de cifra $0$, $10$ de cifra $1$ şi $11$ de cifra $2$ (configuraţia $01$ nu poate apărea). De exemplu, starea $(4, 3, 1000212)$ va reprezenta configuraţia prezentată în următoarea imagine (ultima cifră corespunde primei perechi de pătrăţele, penultima cifră celei de-a doua perechi ş.a.m.d.):
p=. !probleme-de-acoperire-2?P273.jpg!
Dacă decidem să nu punem piesă în pătrăţelul $(4, 3)$ atunci din starea $(4, 3, 1000212)$ trecem în starea $(5, 3, 10000212)$.
Dacă decidem să nu punem piesă în pătrăţelul $(4, 3)$ atunci din starea $(4, 3, 1000212)$ trecem în starea $(5, 3, 1000212)$.
p=. !probleme-de-acoperire-2?P274.jpg!
p=. !probleme-de-acoperire-2?P276.jpg!
Tablei îi adăugăm la sfârşit o coloană pe care nu pot fi aşezate piese. Rezultatul cerut de problemă se va afla în $max[N][M + 1][&#48;]$. Menţionăm că $Problemele$ '$2$':probleme-de-acoperire-2#prob2, '$3$':probleme-de-acoperire-2#prob3 şi '$4$':probleme-de-acoperire-2#prob4 pot fi rezolvate în mod asemănător în complexitate $O(N * M * 2^M^)$.
Tablei îi adăugăm la sfârşit o coloană pe care nu pot fi aşezate piese. Rezultatul cerut de problemă se va afla în $max[N][M + 1][&#48;]$. Menţionăm că problemele '$2$':probleme-de-acoperire-2#problema2, '$3$':probleme-de-acoperire-2#problema3 şi '$4$':probleme-de-acoperire-2#problema4 pot fi rezolvate în mod asemănător în complexitate $O(N * M * 2^M^)$.
h2(#problema8). Problema 8 (Lot 2001, 'SGU Domino':http://acm.sgu.ru/problem.php?contest=0&problem=101, 'IPSC 2004':http://ipsc.ksp.sk/contests/ipsc2004/practice/problems/t.php, Algoritmus 2005, IOI 2005)
h3. Soluţie:
Aceasta este o problemă celebră sau aşa se pare după numărul de concursuri în care a fost folosită şi este o generalizare a unei probleme din articolul precedent.
Aceasta este o problemă celebră, sau aşa se pare după numărul de concursuri în care a fost folosită, şi este o generalizare a unei probleme din 'articolul precedent':probleme-de-acoperire-1.
Prima idee ar fi să încercăm o abordare $greedy$ în care încercăm într-o ordine oarecare să punem piese pe tablă cât timp mai este loc, dar putem găsi uşor contraexemple pentru acest tip de abordare. Limitele sunt mult prea mari pentru ca o rezolvare bazată pe $programare dinamică$ combinată cu $backtracking$ să meargă. O idee ce am utilizat-o în numărul anterior ne va fi folositoare aici. Colorăm tabla noastră în mod asemănător unei table de şah şi numerotăm pătrăţelele tablei.
Prima idee ar fi să încercăm o abordare $greedy$ şi să punem piese pe tablă într-o ordine oarecare cât timp mai este loc. Dar putem găsi uşor contraexemple pentru acest tip de abordare. Limitele sunt mult prea mari pentru ca o rezolvare bazată pe $programare dinamică$ combinată cu $backtracking$ să meargă. O idee ce am utilizat-o în articolul anterior ne va fi folositoare şi aici. Colorăm tabla noastră în mod asemănător unei table de şah şi numerotăm pătrăţelele tablei.
p=. !probleme-de-acoperire-2?P282.jpg!
Acum vedem că un domino poate fi amplasat pe tablă şi el trebuie să ocupe o celulă colorată alb şi una negru, celule care sunt adiacente. Dacă realizăm un graf în care nodurile sunt celulele iar între două noduri există muchie dacă ele sunt adiacente vertical sau orizontal pe tablă, facem observaţia că graful este bipartit. O acoperire cu dominouri corespunde în acest graf unei mulţimi de muchii pentru care nu există două muchii cu acelaşi capăt (o muchie corespunde amplasării posibile a unui domino, iar restricţia menţionată face ca să nu existe dominouri care se suprapun). Deci pentru a găsi o soluţie maximală pentru problema iniţială, trebuie să găsim o mulţime de muchii de cardinal maxim. În acest mod am transformat cerinţa într-o problemă clasică de teoria grafurilor cunoscută sub numele de '$cuplaj maxim într-un graf bipartit$':usaco-ian-2005-divizia-gold#cover. Vedem în imaginea următoare cum a fost transformată tabla într-un graf şi cum soluţia prezentată în exemplu corespunde unui $cuplaj maxim$ în graful asociat tablei.
Acum vedem că un domino amplasat pe tablă trebuie să ocupe o celulă colorată alb şi una negru, celule care sunt adiacente. Dacă realizăm un graf în care nodurile sunt celulele, iar între două noduri există muchie dacă ele sunt adiacente vertical sau orizontal pe tablă, observăm că graful este bipartit. O acoperire cu dominouri corespunde în acest graf unei mulţimi de muchii pentru care nu există două muchii cu acelaşi capăt (o muchie corespunde amplasării posibile a unui domino, iar restricţia menţionată face să nu existe dominouri care se suprapun). Deci pentru a găsi o soluţie maximală pentru problema iniţială, trebuie să găsim o mulţime de muchii neadiacente de cardinal maxim. În acest mod am transformat cerinţa într-o problemă clasică de teoria grafurilor cunoscută sub numele de $cuplaj maxim într-un graf bipartit$. Vedem în imaginea următoare cum a fost transformată tabla într-un graf şi cum soluţia prezentată în exemplu corespunde unui $cuplaj maxim$ în graful asociat tablei.
p=. !probleme-de-acoperire-2?P283.jpg!
h2(#aplicatii). Aplicaţii
* 'Pavare':problema/pavare, infoarena
* 'Pavare':problema/pavare, info{_arena_}
* 'Choco':problema/choco, info{_arena_}
* 'Little Kings':http://acm.sgu.ru/problem.php?contest=0&problem=223, SGU
h2(#bibliografie). Bibliografie
* [1] 'IOI01 Competition':http://olympiads.win.tue.nl/ioi/ioi2001/contest/A-2001-7.pdf
* [2] 'CEOI02 Competition material':http://ics.upjs.sk/ceoi/
* [1] "IOI'01 Competition":http://olympiads.win.tue.nl/ioi/ioi2001/contest/A-2001-7.pdf
* [2] "CEOI'02 Competition material":http://ics.upjs.sk/ceoi/
* [3] 'SGU':http://acm.sgu.ru
* [4] 'TopCoder':http://topcoder.com/tc
* [4] 'TopCoder':http://www.topcoder.com/tc
 

Nu exista diferente intre securitate.

Diferente intre topic forum:

 
3384