gitweb on Svarog

projekti pod git sistemom za održavanje verzija -- projects under the git version control system
Zadatak nalazenje da li postoji put u lavirintu.
authorSasa Tosic <sashat@dmi.uns.ac.rs>
Sat, 28 Nov 2015 15:15:54 +0000 (16:15 +0100)
committerDoni Pracner <quinnuendo@gmail.com>
Sat, 28 Nov 2015 15:15:54 +0000 (16:15 +0100)
Zadatak je predvidjen za prakticne vezbe. Dato je i resenje.

PretrazivanjeSaVracanjem/Lavirint/PostojanjePuta/Lavirint.java [new file with mode: 0644]
PretrazivanjeSaVracanjem/Lavirint/PostojanjePuta/LavirintProgram.java [new file with mode: 0644]
PretrazivanjeSaVracanjem/Lavirint/PostojanjePuta/Mapa.java [new file with mode: 0644]
PretrazivanjeSaVracanjem/Lavirint/PostojanjePuta/lav-prepreke.txt [new file with mode: 0644]
PretrazivanjeSaVracanjem/Lavirint/PostojanjePuta/lav-rupe.txt [new file with mode: 0644]
PretrazivanjeSaVracanjem/Lavirint/PostojanjePuta/lav1.txt [new file with mode: 0644]
PretrazivanjeSaVracanjem/Lavirint/PostojanjePuta/lav2.txt [new file with mode: 0644]
PretrazivanjeSaVracanjem/Lavirint/PostojanjePuta/lavb.txt [new file with mode: 0644]
PretrazivanjeSaVracanjem/Lavirint/PostojanjePuta/lavp.txt [new file with mode: 0644]
PretrazivanjeSaVracanjem/Lavirint/PostojanjePuta/zad-put-u-lavirintu.txt [new file with mode: 0644]

diff --git a/PretrazivanjeSaVracanjem/Lavirint/PostojanjePuta/Lavirint.java b/PretrazivanjeSaVracanjem/Lavirint/PostojanjePuta/Lavirint.java
new file mode 100644 (file)
index 0000000..3dd580f
--- /dev/null
@@ -0,0 +1,86 @@
+/**\r
+ * Klasa Lavirint sadrzi 2 javne i jednu privatnu metodu za trazenje puteva.\r
+ * \r
+ */\r
+\r
+public class Lavirint {\r
+\r
+ // Polje m sadrzi kompletnu mapu\r
+ private Mapa m;\r
+\r
+ // Ucitava mapu iz datog fajla i stampa je na ekran\r
+ Lavirint(String imeFajla) {\r
+  m = Mapa.ucitajIzFajla(imeFajla);\r
+  m.stampaj();\r
+ }\r
+\r
+ // Provarava da li postoji put do izlaza i vraca vrednost true\r
+ // ako postoji put ili vrednost false ako ne postoji\r
+ public boolean postojiPut(int x, int y) {\r
+  if (x < 0 || x >= m.getSirina() || y < 0 || y >= m.getVisina()) {\r
+   return false;\r
+  }\r
+  if (m.getPos(x, y) == true) {\r
+   return false;\r
+  }\r
+  if (m.getMat(x, y) == Mapa.ZID) {\r
+   return false;\r
+  }\r
+  if (m.getMat(x, y) == Mapa.IZLAZ) {\r
+   return true;\r
+  } else {\r
+   m.setPos(x, y, true);\r
+   if (postojiPut(x + 1, y)) {\r
+    return true;\r
+   }\r
+   if (postojiPut(x - 1, y)) {\r
+    return true;\r
+   }\r
+   if (postojiPut(x, y + 1)) {\r
+    return true;\r
+   }\r
+   if (postojiPut(x, y - 1)) {\r
+    return true;\r
+   }\r
+   m.setPos(x, y, false);\r
+   return false;\r
+  }\r
+ }\r
+\r
+ // Poziva metodu rput da pronadje i ispise put, ako postoji\r
+ // Ukoliko put ne postoji, ispisuje poruku o gresci\r
+ public void nadjiPut(int x, int y) {\r
+  if (!rput(x, y)) {\r
+   System.err.println("Ne postoji put");\r
+  }\r
+ }\r
+\r
+ // Proverava da li postoji put korsiteci pretrazivanje sa vracanjem\r
+ // Ukoliko se pronadje izlaz iz lavirinta, stampa se put u obrnutom\r
+ // redosledu\r
+ // Put se stampa pri povratku iz rekurzije\r
+ private boolean rput(int x, int y) {\r
+  if (x < 0 || x >= m.getSirina() || y < 0 || y >= m.getVisina()) {\r
+   return false;\r
+  }\r
+  if (m.getPos(x, y)) {\r
+   return false;\r
+  }\r
+  if (m.getMat(x, y) == Mapa.ZID) {\r
+   return false;\r
+  }\r
+  if (m.getMat(x, y) == Mapa.IZLAZ) {\r
+   System.out.println(x + " " + y);\r
+   return true;\r
+  } else {\r
+   m.setPos(x, y, true);\r
+   if (rput(x + 1, y) || rput(x, y + 1) || rput(x, y - 1)\r
+     || rput(x - 1, y)) {\r
+    System.out.println(x + " " + y);\r
+    return true;\r
+   }\r
+   m.setPos(x, y, false);\r
+   return false;\r
+  }\r
+ }\r
+}\r
diff --git a/PretrazivanjeSaVracanjem/Lavirint/PostojanjePuta/LavirintProgram.java b/PretrazivanjeSaVracanjem/Lavirint/PostojanjePuta/LavirintProgram.java
new file mode 100644 (file)
index 0000000..0532130
--- /dev/null
@@ -0,0 +1,45 @@
+/**\r
+ * Program za nalazenje puta u lavirintu.\r
+ * \r
+ * Date su dve varijante problema\r
+ * \r
+ * Jednostavnije je samo nalazenje da li put postoji.\r
+ * \r
+ * Prosirenje tog resenja nam ispisuje taj nadjeni put.\r
+ */\r
+\r
+public class LavirintProgram {\r
+\r
+ public static void main(String[] args) {\r
+  Svetovid.out.println("Unesite ime fajla: ");\r
+  String fajl = Svetovid.in.readLine();\r
+  if (!Svetovid.testIn(fajl)) {\r
+   System.out.println("Greska: nema fajla!");\r
+   return;\r
+  }\r
+\r
+  Lavirint l = new Lavirint(fajl);\r
+\r
+  if (l != null) {\r
+   System.out.println("1 - da li postoji put");\r
+   System.out.println("2 - ispis nekog puta (ako postoji)");\r
+   System.out.println("Unesite izbor 1-2:");\r
+   int op = Svetovid.in.readInt();\r
+\r
+   switch (op) {\r
+   case 1:\r
+    if (l.postojiPut(0, 0)) {\r
+     System.out.println("Postoji put");\r
+    } else {\r
+     System.out.println("Ne postoji put");\r
+    }\r
+    break;\r
+   case 2:\r
+    l.nadjiPut(0, 0);\r
+    break;\r
+   default:\r
+    System.err.println("Uneli ste pogresan izbor");\r
+   }\r
+  }\r
+ }\r
+}
\ No newline at end of file
diff --git a/PretrazivanjeSaVracanjem/Lavirint/PostojanjePuta/Mapa.java b/PretrazivanjeSaVracanjem/Lavirint/PostojanjePuta/Mapa.java
new file mode 100644 (file)
index 0000000..a5e8a15
--- /dev/null
@@ -0,0 +1,78 @@
+public class Mapa {\r
+ public final static int IZLAZ = -99;\r
+ public final static int ZID = -11;\r
+ public final static int ERROR = Integer.MIN_VALUE;\r
+\r
+ private int visina, sirina;\r
+ private int[][] mat;\r
+ private boolean[][] pos;\r
+\r
+ public int getSirina() {\r
+  return sirina;\r
+ }\r
+\r
+ public int getVisina() {\r
+  return visina;\r
+ }\r
+\r
+ public void setPos(int x, int y, boolean b) {\r
+  if (0 <= x && x < sirina && 0 <= y && y < visina) {\r
+   pos[x][y] = b;\r
+  }\r
+ }\r
+\r
+ public boolean getPos(int x, int y) {\r
+  if (0 <= x && x < sirina && 0 <= y && y < visina) {\r
+   return pos[x][y];\r
+  } else {\r
+   return true;\r
+  }\r
+ }\r
+\r
+ public int getMat(int x, int y) {\r
+  if (0 <= x && x < sirina && 0 <= y && y < visina) {\r
+   return mat[x][y];\r
+  } else {\r
+   return ERROR;\r
+  }\r
+ }\r
+\r
+ public Mapa(int sirina, int visina) {\r
+  this.sirina = sirina;\r
+  this.visina = visina;\r
+  mat = new int[sirina][visina];\r
+  pos = new boolean[sirina][visina];\r
+ }\r
+\r
+ public static Mapa ucitajIzFajla(String imeFajla) {\r
+  if (!Svetovid.testIn(imeFajla)) {\r
+   return null;\r
+  }\r
+\r
+  int sirina = Svetovid.in(imeFajla).readInt();\r
+  int visina = Svetovid.in(imeFajla).readInt();\r
+  if (sirina >= 0 && visina >= 0) {\r
+   Mapa res = new Mapa(sirina, visina);\r
+   for (int j = 0; j < visina; j++)\r
+    for (int i = 0; i < sirina; i++)\r
+     res.mat[i][j] = Svetovid.in(imeFajla).readInt();\r
+   Svetovid.closeIn(imeFajla);\r
+   return res;\r
+  } else {\r
+   Svetovid.closeIn(imeFajla);\r
+   return null;\r
+  }\r
+ }\r
+\r
+ public void stampaj() {\r
+  if (visina != 0 && sirina != 0) {\r
+   System.out.println(visina + " " + sirina);\r
+   for (int j = 0; j < visina; j++) {\r
+    for (int i = 0; i < sirina; i++) {\r
+     System.out.print(mat[i][j] + "\t");\r
+    }\r
+    System.out.println();\r
+   }\r
+  }\r
+ }\r
+}\r
diff --git a/PretrazivanjeSaVracanjem/Lavirint/PostojanjePuta/lav-prepreke.txt b/PretrazivanjeSaVracanjem/Lavirint/PostojanjePuta/lav-prepreke.txt
new file mode 100644 (file)
index 0000000..3839c6d
--- /dev/null
@@ -0,0 +1,10 @@
+8 8\r
+   0   2   3   4   6  55   0 -99\r
+   0 -11   0 -11   7   0   0   0\r
+   0 -11   0 -11   0   0 -11   0\r
+   0   0   2   0 -11   0 -11   0\r
+   0 -11 -11   0 -11   0 -11   0\r
+   0 -11   0   0 -11   0 -11   0\r
+   0 -11 -11   0 -11   0 -11   0\r
+   0   0  44   2   4   0   0   0\r
+\r
diff --git a/PretrazivanjeSaVracanjem/Lavirint/PostojanjePuta/lav-rupe.txt b/PretrazivanjeSaVracanjem/Lavirint/PostojanjePuta/lav-rupe.txt
new file mode 100644 (file)
index 0000000..a519c68
--- /dev/null
@@ -0,0 +1,7 @@
+5 6\r
+   0  -1   0 -11 -99\r
+   0 -11   0 -11   0\r
+   0 -11   0   0   0\r
+   0 -11   0 -11  -1\r
+ -11 -11  -1 -11  -1\r
+   0 -11   0   0   0\r
diff --git a/PretrazivanjeSaVracanjem/Lavirint/PostojanjePuta/lav1.txt b/PretrazivanjeSaVracanjem/Lavirint/PostojanjePuta/lav1.txt
new file mode 100644 (file)
index 0000000..70a9571
--- /dev/null
@@ -0,0 +1,7 @@
+5 6\r
+   0   0   0 -11 -99\r
+   0 -11   0 -11   0\r
+   0 -11   0   0   0\r
+   0 -11   0 -11   0\r
+ -11 -11   0   0   0\r
+   0 -11   0   0 -11\r
diff --git a/PretrazivanjeSaVracanjem/Lavirint/PostojanjePuta/lav2.txt b/PretrazivanjeSaVracanjem/Lavirint/PostojanjePuta/lav2.txt
new file mode 100644 (file)
index 0000000..148f5b5
--- /dev/null
@@ -0,0 +1,10 @@
+8 8\r
+   0   0   0   0   0 -11   0 -99\r
+   0 -11   0 -11   0   0   0   0\r
+   0 -11   0 -11   0   0 -11   0\r
+   0   0   0   0 -11   0 -11   0\r
+   0 -11 -11   0 -11   0 -11   0\r
+   0 -11   0   0 -11   0 -11   0\r
+   0 -11 -11   0 -11   0 -11   0\r
+   0   0 -11   0   0   0   0   0\r
+\r
diff --git a/PretrazivanjeSaVracanjem/Lavirint/PostojanjePuta/lavb.txt b/PretrazivanjeSaVracanjem/Lavirint/PostojanjePuta/lavb.txt
new file mode 100644 (file)
index 0000000..32632c4
--- /dev/null
@@ -0,0 +1,7 @@
+5 6\r
+  0   0   0 -11 -99\r
+  0 -11   0 -11   0\r
+  0 -11   0 -11   0\r
+  0 -11   0 -11   0\r
+-11 -11   0   0 -11\r
+  0 -11   0   0 -11\r
diff --git a/PretrazivanjeSaVracanjem/Lavirint/PostojanjePuta/lavp.txt b/PretrazivanjeSaVracanjem/Lavirint/PostojanjePuta/lavp.txt
new file mode 100644 (file)
index 0000000..0cb506b
--- /dev/null
@@ -0,0 +1,5 @@
+4 4\r
+   0   0   0   0\r
+   0   0   0   0\r
+   0   0   0   0\r
+   0   0   0 -99\r
diff --git a/PretrazivanjeSaVracanjem/Lavirint/PostojanjePuta/zad-put-u-lavirintu.txt b/PretrazivanjeSaVracanjem/Lavirint/PostojanjePuta/zad-put-u-lavirintu.txt
new file mode 100644 (file)
index 0000000..66bec95
--- /dev/null
@@ -0,0 +1,127 @@
+============================================================\r
+  Zadatak - pretrazivanje sa vracanjem - put u lavirintu\r
+============================================================\r
+\r
+\r
+Postavka problema\r
+============================================================\r
+\r
+Neka je dat lavirint kao matrica polja, pri cemu razlicite \r
+vrednosti polja imaju razlicito znacenje. Potrebno je pronaci\r
+put kroz lavirint od pocetnog polja, do izlaza iz lavirinta,\r
+pri cemu se pod putem smatra niz polja koja je potrebno \r
+posetiti u datom redosledu, da bi se stiglo od pocetnog polja\r
+do cilja. Pri obilasku lavirinta, sa jednog polja je moguce \r
+preci na susedno ako ona imaju istu ivicu, tj. ako se ono \r
+nalazi odmah levo, desno, gore ili dole u odnosu na trenutno \r
+polje.\r
+\r
+Znacenja vrednosti polja su;\r
+0   = slobodno polje u lavirintu na koje je dozvoljeno stati\r
+-11 = zid, polje na koje nije dozvoljeno stati\r
+-99 = izlaz iz lavirinta\r
+\r
+\r
+Format fajla\r
+------------------------------------------------------------\r
+\r
+Mapa je u fajlu predstavljena na sledeci nacin:\r
+\r
+U prvom redu se nalaze dva broja S i V koji predstavljaju\r
+sirinu i visinu mape.\r
+\r
+U sledecih V redova se nalaze po S celih brojeva koji\r
+predstavljaju vrednosti polja u lavirintu.\r
+\r
+Polje (0, 0) nalazi se u gornjem levom polju matrice.\r
+\r
+\r
+Primeri\r
+------------------------------------------------------------\r
+\r
+Za testiranje programa su dati su fajlovi:\r
+"lav1.txt" i "lav2.txt" u kojima postoji resenje\r
+"lavp.txt" koji ne sadrzi zidove\r
+"lavb.txt" u kojem nije moguce naci resenje\r
+\r
+"lav-rupe.txt" za testiranje modifikacije zadatka sa rupama\r
+"lav-prepreke.txt" za testiranje modifikacije zadatka sa preprekama\r
+\r
+Modifikacije su opisane na kraju teksta.\r
+\r
+\r
+Zadatak\r
+============================================================\r
+\r
+Napisati klasu LavirintProgram koja ucitava ime fajla u kojem\r
+se nalazi definisan lavirint, koordinate pocetne pozicije \r
+(x, y) od koje se trazi izlaz iz lavirinta, kao i izbor sta \r
+zelimo da radimo. Nakon ucitanog izbora, klasa treba da ucita\r
+lavirint iz datog fajla, ispise ga na ekran i izvrsi izabranu\r
+operaciju. \r
+\r
+Ponuditi korisniku sledeci izbor:\r
+1 - provera da li postoji put od unetog polja do izlaza\r
+2 - ispis puta ukoliko postoji, odnosno ispis poruke da put \r
+    ne postoji\r
+\r
+\r
+Pretrazivanje sa vracanjem\r
+------------------------------------------------------------\r
+\r
+Jedan od nacina da se uradi zadatak je koriscenjem pretrazivanja\r
+sa vracanjem (poznatom u literaturi pod engleskim nazivom\r
+"backtrack"). \r
+\r
+Ideja je jednostavna, krenemo od prvog polja, oznacimo ga\r
+kao poseceno i pokusamo da se prebacimo na bilo koje\r
+neobidjeno susedno. Na tom polju ponovimo isti postupak i\r
+tako nastavljamo dok ne naidjemo na izlaz ili dok vise\r
+nemamo gde da idemo. \r
+\r
+Ukoliko nismo naisli na izlaz, a nemamo gde dalje da idemo,\r
+onda oznacimo trenutno polje kao neobidjeno i vratimo se\r
+jedno polje nazad i probamo nekog drugog suseda. Ako vise\r
+nema suseda vratimo se jos jedno polje. Ukoliko vise nema\r
+gde da se vracamo znaci da se do izlaza ne moze doci.\r
+\r
+Backtrack je najlakse izvoditi rekurzivno, tako da se poziv\r
+procedure vrsi za pojedinacno polje. Ovako se povratkom iz\r
+rekurzije vracamo na polje odakle smo dosli.\r
+\r
+\r
+Jedna od mogucih varijanti ideje procedure:\r
+\r
+rek(i,j,...)\r
+- nije u matrici?  -> izlaz\r
+- zid?  -> izlaz\r
+- poseceno polje? -> izlaz\r
+- da li je kraj? -> obradimo resenje\r
+- inace trazimo dalje\r
+-   postavimo da je poseceno polje\r
+-   pokusamo da obidjemo sve susede:\r
+-       rek(i+1,j,..)\r
+-       rek(i-1,j,..)\r
+-       rek(i,j+1,..)\r
+-       rek(i,j-1,..)\r
+-   postavimo da polje nije poseceno\r
+\r
+\r
+Prosirenje zadatka:\r
+------------------------------------------------------------ \r
+\r
+Neka je dat lavirint sa sledecim dodatnim poljima:\r
+-1 = rupa na putu\r
+bilo koji pozitivan broj = visina prepreke na putu\r
+\r
+Modifikovati postojece metode za trazenje puta tako da:\r
+- omogucavaju preskakanje rupa, ali samo ako je rupa velicine\r
+  jednog polja. Rupe koje su u datom pravcu duze od jednog \r
+  polja ne preskakati\r
+- omogucava penjanje po preprekama, ali samo po preprekama \r
+  koje su za najvise 3 vislje od visine trenutnog polja. \r
+  Ukoliko se vec nalazimo na prepreci, dozvoljeno je preci na\r
+  vislju prepreku, ukoliko ona nije veca za vise od 3 od \r
+  postojece prepreke. Silazak sa prepreke je moguc na bilo \r
+  koje polje osim zida\r
+- omogucava preskakanje prepreka, ali najvise 4 puta\r
Svarog.pmf.uns.ac.rs/gitweb maintanance Doni Pracner