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
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
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