Informatika feladatmegoldó verseny Kiss Elemér Szakkollégium 2013. február 19. Dr. Kovács Lehel István
Állás
Összesítő
Új feladat 5. forduló
4. Feladat A prímszámok generálása ősi matematikai feladat. Írjunk minél gyorsabb algoritmust, amely 350 000 000-ig legenerálja a prímszámokat!
Be / Ki BE: 350 000 000 KI: Állomány prímszámokkal Generálási idő
Határidő 2013. március 17. 24 óra Beküldeni (név, szak, évfolyam, kód): klehel77@yahoo.com
Megoldások
Feladatok 1. feladat Gyors darabolás 2. feladat Szomszédok 3. feladat Huszárok
I.
1. feladat Adjunk minél gyorsabb algoritmust (C, C++ programot) a következő feladat megoldására: Az nyer, akinek a programja a leggyorsabb (mérjük a futási időt)!
Feladat Adott egy A hosszúságú rúd. Hányféleképpen vághatjuk fel A 1, A 2,..., A n hosszúságú darabokra a rudat, úgy hogy mindegyik darabból legfennebb egyet használunk.
Példa A = 33 A 1 = 1 A 2 = 4 A 3 = 7 A 4 = 8 A 5 = 9 A 6 = 10 A 7 = 14 A 8 = 15 A 9 = 18
Megoldás Backtracking Valami jobb...
A matematikai modell SDE Speciális Diofantoszi Egyenlet: a 1 x 1 + a 2 x 2 + + a n x n = a ahol: x i {0, 1}
Az egyenlet megoldása Aritmetikai módszer Geometriai módszer Algoritmus Backtracking Linearizálás Maszkolással
Backtracking procedure back(i: integer; len: integer; eq: TIntArray; var bin: TIntArray; res: integer; var sol: TSolution; var solnr: integer); begin if i = len-1 then begin if Sum(len, eq, bin) = res then Solution(len, bin, sol, solnr) end else begin bin[i+1] := 0; back(i+1, len, eq, bin, res, sol, solnr); bin[i+1] := 1; back(i+1, len, eq, bin, res, sol, solnr); end; end;
Linearizálás n a feladat rendje n-hosszúságú bináris regiszter: 0 0 0 0 0 0 0 1 2 3 4 n 1 1 1 1 1 1 1 0 1 2 3 4 n 1
Maszkolás Ugyanaz, csak egy regiszterben megvalósítható eltolás <<, >> operátorok segítségével.
II.
2. feladat Adott n és m, valamint k (1<=k<=8). A következő elvek betartásával rendezzük be egy nxm-es mátrixba a 2, 4, 8, 16,..., 2 k számokat úgy, hogy a mátrix elemeinek összege maximális legyen: - a 2-ot bárhova beírhatjuk - a 4-nek kell hogy legyen legalább egy 2-es szomszédja - a 8-nak kell hogy legyen legalább egy 2-es és egy 4-es szomszédja - a 16-nak kell hogy legyen legalább egy 2-es, egy 4-es, egy 8-as szomszédja -... - 2 k -nak kell hogy legyen legalább egy 2-es, egy 4-es, egy 8-as,..., egy 2 k-1 -es szomszédja
Be / Ki Be: n m k Ki: mátrix összeg
Szomszéd X X X X o X X X X
Például n = 3 m = 3 8 4 8 k = 3 8 2 8 8 4 8
III.
3.1. Feladat Egy 8 8-as sakktáblára elhelyezünk egy huszárt. A huszár lóugrásban lép, azaz vagy vízszintes irányban lép egyet és függőlegesen kettőt, vagy pedig fordítva. Készíts programot, amely egy adott pozícióra elhelyezett huszár esetén megadja, hogy a huszár mely pozíciókra minimum hány lépésben juthat el! (Forrás: NEMES TIHAMÉR SZÁMÍTÁSTECHNIKA VERSENY 2009)
Be / Ki A BE.IN szöveges állomány első sorában a tesztesetek száma található, majd mindegyik teszteset egyetlen sorában a huszár sorindexe (1 SOR 8) és oszlopindexe (1 OSZLOP 8) van, egy szóközzel elválasztva. A képernyőre mindegyik tesztesetre 8 sort kell írni, mindegyikben 8 szám legyen egy-egy szóközzel elválasztva! Az i-edik sor j-edik oszlopában az a lépésszám legyen, ahány lépésben az adott mező elérhető a kiinduló mezőről! A teszteseteket egy üres sorral kell elválasztani.
Példa Be: 1 3 2 Ki: 1 2 1 4 3 2 3 4 2 3 2 1 2 3 4 3 3 0 3 2 3 2 3 4 2 3 2 1 2 3 4 3 1 2 1 4 3 2 3 4 2 3 2 3 2 3 4 3 3 2 3 2 3 4 3 4 4 3 4 3 4 3 4 5
Adatok #include <cstdio> #include <cstring> #include <queue> using namespace std; struct node { int x; int y; node(int xx, int yy){x = xx; y = yy;}; }; int hx, hy; int cache[10][10]; int inq[10][10]; const int dx[] = { 2, 2, 1, 1, -2, -2, -1, -1}; const int dy[] = { 1, -1, 2, -2, 1, -1, 2, -2};
Főprogram int main() { freopen("sakk.be","r",stdin); freopen("sakk.ki","w",stdout); memset(cache, -1, sizeof(cache)); memset(inq, 0, sizeof(inq)); read(); solve(hx, hy); print(); return 0; }
read void read() { scanf("%d%d", &hx, &hy); } inline int good(int x, int y) { if (x > 0 && x < 9 && y > 0 && y < 9) return 1; return 0; }
print void print() { int i, j; for (i = 1; i < 9; ++i) { for (j = 1; j < 9; ++j) printf("%d ", cache[i][j]); printf("\n"); } }
solve void solve(int hx, int hy) { queue<node> q; q.push(node(hx,hy)); cache[hx][hy] = 0; while (!q.empty()) { int x = q.front().x; int y = q.front().y; q.pop(); inq[x][y] = 0; int k, newx, newy;
solve for (k = 0; k < 8; ++k) { newx = x + dx[k]; newy = y + dy[k]; if (!good(newx, newy)) continue; if (cache[newx][newy] == -1 (cache[newx][newy] > cache[x][y] + 1)) { cache[newx][newy] = cache[x][y] + 1; if (!inq[newx][newy]) { inq[newx][newy] = 1; q.push(node(newx,newy)); } } } } }
3.2. Feladat Egy 8 8-as sakktáblára elhelyezünk egy huszárt, amellyel két játékos felváltva lép. Aki nem tud olyan mezőre lépni, ahol még nem járt a huszár, az veszít. Kinek van nyerő stratégiája? Szimuláljuk le a játékot!
Be / Ki BE: A huszár kezdeti pozíciója. A kezdő fél (ember / szamítógép, ember 1 / ember 2) KI: A kétszemélyes játék lejátszása