From: Sasa Tosic Date: Sat, 5 Dec 2015 10:58:35 +0000 (+0100) Subject: Lavirint - trazenje najboljeg puta X-Git-Url: https://svarog.pmf.uns.ac.rs/gitweb/?a=commitdiff_plain;h=572437043c8e9dd5343cdda3a656f2c8f7a638ae;p=spa2-materijali.git Lavirint - trazenje najboljeg puta --- diff --git a/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/LavirintProgramV2.java b/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/LavirintProgramV2.java new file mode 100644 index 0000000..1b1c4ae --- /dev/null +++ b/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/LavirintProgramV2.java @@ -0,0 +1,52 @@ +/** + * Program za nalazenje puta u lavirintu. + * + * Opcija tri nalazi sve puteve i medju njima bira najkraci. + * + * Opcija cetiriresava lavirint u kome su rasuti zlatnici na poljima i + * nalazi put na kome se kupi najvise zlatnika. + */ + +public class LavirintProgramV2 { + + public static void main(String[] args) { + Svetovid.out.println("Unesite ime fajla: "); + String fajl = Svetovid.in.readLine(); + if (!Svetovid.testIn(fajl)) { + System.out.println("Greska: nema fajla!"); + return; + } + + LavirintV2 l = new LavirintV2(fajl); + Resenje r; + + if (l != null) { + System.out.println("3 - nalazenje najkraceg puta"); + System.out.println("4 - nalazenje najvrednijeg puta"); + System.out.println("Unesite izbor 1-4:"); + int op = Svetovid.in.readInt(); + + switch (op) { + case 3: + r = l.najkraciPut(0, 0); + if (r != null) { + r.stampaj(); + } else { + System.out.println("Nema resenja"); + } + break; + case 4: + r = l.najvrednijiPut(0, 0); + if (r != null) { + r.stampaj(); + System.out.println("Vrednost puta: " + r.getVrednost()); + } else { + System.out.println("Nema resenja"); + } + break; + default: + System.err.println("Uneli ste pogresan izbor"); + } + } + } +} \ No newline at end of file diff --git a/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/LavirintV2.java b/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/LavirintV2.java new file mode 100644 index 0000000..57a536a --- /dev/null +++ b/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/LavirintV2.java @@ -0,0 +1,86 @@ +/** + * Klasa Lavirint sadrzi 2 javne i jednu privatnu metodu za trazenje puteva. + * + * Klase KomparatorPoDuzini i KomparatorPoVrednosti predstavljaju komparatore + * koji se korste pri trazenju najkraceg i najvrednijeg puta. + */ + +import java.util.Comparator; + +public class LavirintV2 { + + // Polje m sadrzi kompletnu mapu + private Mapa m; + // Polje optResenje sluzi za pamcenje optimalnog resenja + private Resenje optResenje; + + // Ucitava mapu iz datog fajla i stampa je na ekran + LavirintV2(String imeFajla) { + m = Mapa.ucitajIzFajla(imeFajla); + m.stampaj(); + } + + // Kreira optimalno resenje za put, pri cemu se za optimalnost resenja + // koristi komparator po duzini resenja, tj. trazi se najkrace resenje + // Samo resenje kreira se u metodi optPut + public Resenje najkraciPut(int x, int y) { + Resenje r = new Resenje(); + optPut(x, y, r, new KomparatorPoDuzini()); + return optResenje; + } + + // Kreira optimalno resenje za put, pri cemu se za optimalnost resenja + // koristi komparator po duzini resenja, tj. trazi se najvrednije resenje + // Samo resenje kreira se u metodi optPut + public Resenje najvrednijiPut(int x, int y) { + Resenje r = new Resenje(); + optPut(x, y, r, new KomparatorPoVredosti()); + return optResenje; + } + + // Proverava da li postoji put korsiteci pretrazivanje sa vracanjem + // Ukoliko se pronadje na prvi ili optimalniji put, taj put se pamti u + // optResenje + // Optimalnost resenja se proverava komparatorom + private void optPut(int x, int y, Resenje r, Comparator c) { + if (x < 0 || x >= m.getSirina() || y < 0 || y >= m.getVisina()) { + return; + } + if (m.getPos(x, y)) { + return; + } + if (m.getMat(x, y) == Mapa.ZID) { + return; + } + if (m.getMat(x, y) == Mapa.IZLAZ) { + r.dodaj(x, y, 0); + if (optResenje == null || c.compare(r, optResenje) < 0) { + optResenje = r.clone(); + } + r.izbaciKraj(); + } else { + m.setPos(x, y, true); + r.dodaj(x, y, m.getMat(x, y)); + optPut(x + 1, y, r, c); + optPut(x, y + 1, r, c); + optPut(x, y - 1, r, c); + optPut(x - 1, y, r, c); + m.setPos(x, y, false); + r.izbaciKraj(); + } + } +} + +// Komparator za resenja po duzini resenja +class KomparatorPoDuzini implements Comparator { + public int compare(Resenje r1, Resenje r2) { + return r1.getLength() - r2.getLength(); + } +} + +// Komparator za resenja po vrednosti resenja +class KomparatorPoVredosti implements Comparator { + public int compare(Resenje r1, Resenje r2) { + return r2.getVrednost() - r1.getVrednost(); + } +} \ No newline at end of file diff --git a/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/Mapa.java b/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/Mapa.java new file mode 100644 index 0000000..a5e8a15 --- /dev/null +++ b/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/Mapa.java @@ -0,0 +1,78 @@ +public class Mapa { + public final static int IZLAZ = -99; + public final static int ZID = -11; + public final static int ERROR = Integer.MIN_VALUE; + + private int visina, sirina; + private int[][] mat; + private boolean[][] pos; + + public int getSirina() { + return sirina; + } + + public int getVisina() { + return visina; + } + + public void setPos(int x, int y, boolean b) { + if (0 <= x && x < sirina && 0 <= y && y < visina) { + pos[x][y] = b; + } + } + + public boolean getPos(int x, int y) { + if (0 <= x && x < sirina && 0 <= y && y < visina) { + return pos[x][y]; + } else { + return true; + } + } + + public int getMat(int x, int y) { + if (0 <= x && x < sirina && 0 <= y && y < visina) { + return mat[x][y]; + } else { + return ERROR; + } + } + + public Mapa(int sirina, int visina) { + this.sirina = sirina; + this.visina = visina; + mat = new int[sirina][visina]; + pos = new boolean[sirina][visina]; + } + + public static Mapa ucitajIzFajla(String imeFajla) { + if (!Svetovid.testIn(imeFajla)) { + return null; + } + + int sirina = Svetovid.in(imeFajla).readInt(); + int visina = Svetovid.in(imeFajla).readInt(); + if (sirina >= 0 && visina >= 0) { + Mapa res = new Mapa(sirina, visina); + for (int j = 0; j < visina; j++) + for (int i = 0; i < sirina; i++) + res.mat[i][j] = Svetovid.in(imeFajla).readInt(); + Svetovid.closeIn(imeFajla); + return res; + } else { + Svetovid.closeIn(imeFajla); + return null; + } + } + + public void stampaj() { + if (visina != 0 && sirina != 0) { + System.out.println(visina + " " + sirina); + for (int j = 0; j < visina; j++) { + for (int i = 0; i < sirina; i++) { + System.out.print(mat[i][j] + "\t"); + } + System.out.println(); + } + } + } +} diff --git a/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/Polje.java b/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/Polje.java new file mode 100644 index 0000000..c40fc5f --- /dev/null +++ b/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/Polje.java @@ -0,0 +1,30 @@ +/** + * Klasa Polje se koristi za pamcenje x i y koordinata nekog polja, kao i + * vrednosti na toj poziciji u mapi + */ + +public class Polje { + private int x, y, v; + + Polje(int x, int y, int v) { + this.x = x; + this.y = y; + this.v = v; + } + + public int getX() { + return x; + } + + public int getY() { + return y; + } + + public int getV() { + return v; + } + + public String toString() { + return x + " " + y + " " + v; + } +} \ No newline at end of file diff --git a/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/Resenje.java b/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/Resenje.java new file mode 100644 index 0000000..e29f569 --- /dev/null +++ b/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/Resenje.java @@ -0,0 +1,72 @@ +/** + * Klasa Resenje koristi se za pamcenje pronadjenog puta. + * + * Polje Polja se koristi za pamcenje svih polja na putu. + * + * Polje nepromenljivaListaPolja je dodata da se omoguci + * pristup poljima resenja "spolja" (za proveru kvaliteta puta na primer), + * ali tako da ne moze da se utice na sam sadrzaj te liste. + */ +import java.util.ArrayList; +import java.util.List; +import java.util.Collections; + +public class Resenje implements Cloneable { + private ArrayList polja; + + Resenje() { + polja = new ArrayList(); + } + + // Dodaje pulje u resenje + public void dodaj(int x, int y, int v) { + polja.add(new Polje(x, y, v)); + } + + // Izbacuje polje iz resenja + public void izbaciKraj() { + if (getLength() > 0) { + polja.remove(getLength() - 1); + } else { + System.err.println("greska: resenje je vec prazno"); + } + } + + // Stampa resenje + public void stampaj() { + System.out.println(getLength()); + for (int i = 0; i < getLength(); i++) + System.out.println(polja.get(i)); + } + + // Vraca duzinu resenja + public int getLength() { + return polja.size(); + } + + // Vraca i-to polje na putu. Ne koristi se u ovoj verziji zadatka. + // Moze se koristiti za proveru kvaliteta resenja + public Polje getPolje(int i) { + return polja.get(i); + } + + // Kreira klon od resenja + @Override + public Resenje clone() { + Resenje rez = new Resenje(); + for (Polje p : polja) { + rez.dodaj(p.getX(), p.getY(), p.getV()); + } + return rez; + } + + // Vraca vrednost puta + // Vrednost se definise kao zbir svih vrednosti polja na putu + public int getVrednost() { + int rez = 0; + for (Polje p : polja) { + rez = rez + p.getV(); + } + return rez; + } +} diff --git a/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/blago1.txt b/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/blago1.txt new file mode 100644 index 0000000..5105c10 --- /dev/null +++ b/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/blago1.txt @@ -0,0 +1,5 @@ +5 4 + 0 0 5 0 0 + 0 4 -1 0 0 + 0 1 -1 -1 -1 + 5 0 0 0 -5 diff --git a/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/blago2.txt b/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/blago2.txt new file mode 100644 index 0000000..7bfb346 --- /dev/null +++ b/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/blago2.txt @@ -0,0 +1,6 @@ +5 5 + 0 0 0 -1 -5 + 7 -1 0 -1 0 + 0 -1 3 3 5 + 0 -1 1 -1 0 +-1 -1 15 0 0 diff --git a/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/blago3.txt b/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/blago3.txt new file mode 100644 index 0000000..28a830e --- /dev/null +++ b/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/blago3.txt @@ -0,0 +1,10 @@ +8 9 + 0 0 0 4 0 2 0 0 +-1 -1 -1 -1 -1 -1 0 -1 + 0 4 0 3 0 0 0 -1 + 0 2 5 1 0 6 0 -1 + 0 -1 -1 -1 0 0 12 -1 + 0 10 -5 1 -1 0 0 -1 +-1 -1 -1 0 0 6 0 1 + 0 -1 20 0 -1 0 -1 0 +-1 -1 0 15 0 0 -1 99 diff --git a/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/blago4.txt b/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/blago4.txt new file mode 100644 index 0000000..3839c6d --- /dev/null +++ b/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/blago4.txt @@ -0,0 +1,10 @@ +8 8 + 0 2 3 4 6 55 0 -99 + 0 -11 0 -11 7 0 0 0 + 0 -11 0 -11 0 0 -11 0 + 0 0 2 0 -11 0 -11 0 + 0 -11 -11 0 -11 0 -11 0 + 0 -11 0 0 -11 0 -11 0 + 0 -11 -11 0 -11 0 -11 0 + 0 0 44 2 4 0 0 0 + diff --git a/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/lav1.txt b/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/lav1.txt new file mode 100644 index 0000000..70a9571 --- /dev/null +++ b/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/lav1.txt @@ -0,0 +1,7 @@ +5 6 + 0 0 0 -11 -99 + 0 -11 0 -11 0 + 0 -11 0 0 0 + 0 -11 0 -11 0 + -11 -11 0 0 0 + 0 -11 0 0 -11 diff --git a/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/lav2.txt b/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/lav2.txt new file mode 100644 index 0000000..148f5b5 --- /dev/null +++ b/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/lav2.txt @@ -0,0 +1,10 @@ +8 8 + 0 0 0 0 0 -11 0 -99 + 0 -11 0 -11 0 0 0 0 + 0 -11 0 -11 0 0 -11 0 + 0 0 0 0 -11 0 -11 0 + 0 -11 -11 0 -11 0 -11 0 + 0 -11 0 0 -11 0 -11 0 + 0 -11 -11 0 -11 0 -11 0 + 0 0 -11 0 0 0 0 0 + diff --git a/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/lavb.txt b/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/lavb.txt new file mode 100644 index 0000000..32632c4 --- /dev/null +++ b/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/lavb.txt @@ -0,0 +1,7 @@ +5 6 + 0 0 0 -11 -99 + 0 -11 0 -11 0 + 0 -11 0 -11 0 + 0 -11 0 -11 0 +-11 -11 0 0 -11 + 0 -11 0 0 -11 diff --git a/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/lavp.txt b/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/lavp.txt new file mode 100644 index 0000000..0cb506b --- /dev/null +++ b/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/lavp.txt @@ -0,0 +1,5 @@ +4 4 + 0 0 0 0 + 0 0 0 0 + 0 0 0 0 + 0 0 0 -99 diff --git a/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/zadatak-najbolji-put.txt b/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/zadatak-najbolji-put.txt new file mode 100644 index 0000000..8c1d6a5 --- /dev/null +++ b/PretrazivanjeSaVracanjem/Lavirint/NajboljiPut/zadatak-najbolji-put.txt @@ -0,0 +1,101 @@ +============================================================ + Zadatak - pretrazivanje sa vracanjem - svi putevi +============================================================ + + +Postavka problema +============================================================ + +Neka je dat lavirint kao matrica polja, pri cemu razlicite +vrednosti polja imaju razlicito znacenje. Potrebno je pronaci +OPTIMALAN put kroz lavirint od pocetnog polja, do izlaza iz +lavirinta, pri cemu se pod putem smatra niz polja koja je +potrebno posetiti u datom redosledu, da bi se stiglo od +pocetnog polja do cilja. Pri obilasku lavirinta, sa jednog +polja je moguce preci na susedno ako ona imaju istu ivicu, +tj. ako se ono nalazi odmah levo, desno, gore ili dole u +odnosu na trenutno polje. + +Znacenja vrednosti polja su; +0 = slobodno polje u lavirintu na koje je dozvoljeno stati +-11 = zid, polje na koje nije dozvoljeno stati +-99 = izlaz iz lavirinta +bilo koji pozitivan broj = vrednost blaga na tom polju + +Format fajla +------------------------------------------------------------ + +Mapa je u fajlu predstavljena na sledeci nacin: + +U prvom redu se nalaze dva broja S i V koji predstavljaju +sirinu i visinu mape. + +U sledecih V redova se nalaze po S celih brojeva koji +predstavljaju vrednosti polja u lavirintu. + +Polje (0, 0) nalazi se u gornjem levom polju matrice. + + +Primeri +------------------------------------------------------------ + +Za testiranje programa su dati su fajlovi: +"lav1.txt" i "lav2.txt" u kojima postoji resenje +"lavp.txt" koji ne sadrzi zidove +"lavb.txt" u kojem nije moguce naci resenje +"blago*.txt" za testiranje zadatka sa blagom + + +Zadatak +============================================================ + +Napisati klasu LavirintProgram koja ucitava ime fajla u kojem +se nalazi definisan lavirint, koordinate pocetne pozicije +(x, y) od koje se trazi izlaz iz lavirinta, kao i izbor sta +zelimo da radimo. Nakon ucitanog izbora, klasa treba da ucita +lavirint iz datog fajla, ispise ga na ekran i izvrsi izabranu +operaciju. + +Ponuditi korisniku sledeci izbor: +3 - ispis najkraceg puta od unetog polja do izlaza +4 - ispis najvrednijeg puta od unetog polja do izlaza + + +Modifikacija pretrazivanja sa vracanjem +------------------------------------------------------------ + +Jedan od nacina da se uradi zadatak je koriscenjem modifikacije +pretrazivanja sa vracanjem. Potrebne modifikacije su sledece: + +1. Nakon dolaska na odredjeno polje u lavirintu potrebno je +to polje ubaciti na kraj trenutnog puta od pocetka lavirinta +do trenutnog polja +2. Nakon povratka sa polja, potrebno je to polje izabaciti sa +kraja trenutnog puta +3. Prilikom obilaska izlaza, potrebno je trenutnu vrednost +puta uporediti sa do sada najoptimalnijim pronadjenim putem +i ukoliko je trenutni put bolji, kopirati ga u optimalan put +4. Vratiti optimalan put ako postoji ili vrednost null ako ne +postoji + + +Neobavezne preporuke: +------------------------------------------------------------ + +1. Kreirati posebnu klasu Resenje koja ce pamtiti resenje. +Resenje pamtiti kao niz ili listu polja, od cega za svako +polje treba zapamtiti koordinate polja i vrednost +2. Prilikom uporedjivanja resenja, koristiti komparatore +3. Za racunanje vrednosti puta koristiti metode koje su deo +klase put (npr. getSize() i getValue()) + + +Prosirenje zadatka: +------------------------------------------------------------ + +Modifikovati postojece metode za trazenje puta tako da: + +- pronalaze put sa najvrednijim blagom pojedinacno +- pronalaze put na kojem postoji najvise polja sa blagom +- pronalaze put na kojem postoji najvise uzastopnih polja sa + blagom