Matematické Fórum

Nevíte-li si rady s jakýmkoliv matematickým problémem, toto místo je pro vás jako dělané.

Nástěnka
22. 8. 2021 (L) Přecházíme zpět na doménu forum.matweb.cz!
04.11.2016 (Jel.) Čtete, prosím, před vložení dotazu, děkuji!
23.10.2013 (Jel.) Zkuste před zadáním dotazu použít některý z online-nástrojů, konzultovat použití můžete v sekci CAS.

Nejste přihlášen(a). Přihlásit

#1 13. 05. 2016 18:11 — Editoval cetis (13. 05. 2016 18:22)

cetis
Příspěvky: 53
Škola: MFF UK
Pozice: student
Reputace:   
 

Přesný baťoh

Zdravím,

prosím Vás, potřeboval bych pomoct s problémem batohu. Mám tohle zadání:

Ze standardního vstupu přečtěte 2 řádky. Na prvním řádku bude celé kladné číslo S <= 10000. Na druhém řádku bude nejprve celé kladné číslo N <= 20, a pak následuje mezerami oddělená posloupnost N celých kladných čísel menších než 10000.
Napište program, který zjistí, zda ze zadané posloupnosti lze vybrat podposloupnost, jejíž součet je S. Pokud nějaká taková podposloupnost existuje, zapište ji na standardní výstup. Pokud podposloupnost se zadaným součtem neexistuje, zapište na standardní výstup slovo "NELZE".

Můj problém spočívá v tom, že mi nejdou vypsat předměty, které se do batohu vejdou. Úlohu řeším pomocí dynamického programování. Zdrojový kód je napsaný v C#. Budu rád za jakýkoliv rady.
Děkuji

            S = MyReader.ReadInt();    // objem batohu
            N = MyReader.ReadInt();   // počet předmětů
            int[] predmety = new int[21];
            int[,] M = new int[21, 10001];
            int[,] pole = new int[210,210];
            int[,] seznam = new int[100,100];
            predmety[0] = 0;
            for (int i = 0; i < N; i++)
                predmety[i] = MyReader.ReadInt();

            for (int i = 0; i <= S; i++)
            {
                M[0, i] = 0;
                pole[0, i] = 0;
            }
            for (int i = 1; i <= N;i++)
            {
                for (int j=0; j <= S;j++ )
                {
                    if (predmety[i-1] > j)
                    {
                        M[i,j] = M[i - 1,j];
                        pole[i-1, j] = 0;
                    }
                    else
                    {
                        M[i, j] = Math.Max(M[i - 1, j], predmety[i - 1] + M[i - 1, j - predmety[i - 1]]);
                        if (M[i, j] == predmety[i - 1] + M[i - 1, j - predmety[i - 1]])
                        {
                            pole[i-1, j] = 1;
                            seznam[i, j] = predmety[i - 1];
                        }
                        else pole[i-1, j] = 0;
                        }
                    }     
            }
            Console.Write("Predmety: ");    //předměty, které se vejdou do baťohu
            K = S;
            for (int i = N; i >= 1; i--)
            {
                if (pole[i-1, K] == 1)
                {
                    Console.Write("{0} ",i);
                    K = K - predmety[i];
                }
           
            }

                Console.WriteLine("Maximalni hmotnost: {0}", M[N, S]);

Offline

 

#2 13. 05. 2016 21:20

dzejkob
Zelenáč
Příspěvky: 10
Reputace:   
 

Re: Přesný baťoh

Ten kód mě připadá docela masakr:

int[,] M = new int[21, 10001];

Takový prostor snad není potřeba. Jinak jsem ten kód moc nepochopil.

Já bych to řešil prostě klasicky nějakým stavovým stromem.

Nebo úplně jednoduše rekurzí:

void (array indexy_pouzitych_predmetu, array & predmety, int cilovy_soucet, array_of_array & vysledek) {
  // kod
}

kód schématicky - už si nepamatuju ty syntaxe

- na začátku projedu všechny předměty a pustím je do té funkce o jednoprvkovém indexy_pouzitych_predmetu

- no a ta funkce jednoduše vyzkouší, zda není součet hodnot předmětů stejný, jako cilovy_soucet - pokud je, tak posloupnost přidá do vysledek a větev končí

- pokud není a hlavně je menší (tj. má smysl testovat další prvky), tak přidávám všechny další prvky, které tam ještě nejsou, a spouštím rekurzi znovu

- až doběhnou všechny rekurze, tak ve vysledek budou všechny podposloupnosti nebo nic


když to je v C#, tak bych udělal jeden objekt, který by v jedné instanci držel všechny stavy a ta rekurzivně volaná metoda by předávala pole použitých předmětů

Offline

 

Zápatí

Powered by PunBB
© Copyright 2002–2005 Rickard Andersson