Sunteți pe pagina 1din 7

Note de laborator Specializare

Algoritmi si structuri de date 2 Info 1

Laborator 2
Descriere: Backtracking - 2

1. Problema labirintului

Se dă un labirint sub forma unei matrici cu m linii şi n coloane. Fiecare element al matricei
reprezintă o cameră. Într-una din camerele labirintului se găseşte un om. Se cere să se afle toate
soluţiile de ieşire din labirint, fără să treacă de două ori prin aceeaşi cameră. Fiecare cameră are
pereţi proprii şi se poate trece dintr-o cameră în alta, numai dacă între cele două camere nu există
perete. Deplasarea prin labirint se poate face doar mergând în sus, în jos, la stânga sau la dreapta,
nu şi în diagonală.

Exemplu: Fie un labirint 4 x 7, codificat printr-o matrice (1 = cale, 0 = zid). Se cere să se


determine toate posibilităţile de ieşire din labirint, pornind dintr-un punct dat (i,j).

public class Labirint {

private int[][] lab = {{0,0,1,1,0,0,0},


{0,0,0,1,0,1,0},
{0,0,0,1,1,1,0},
{0,1,1,1,0,0,0}};

private int [][] sol;


private int [] vert = {-1,0,1,0};
private int [] oriz = {0,1,0,-1};
private int n = 4,m = 7, nrSol = 0;

public Labirint(int i, int j){


sol = new int[n][m];
sol[i][j] = 1;
traseu(i,j,2);
}

private void traseu(int i, int j, int pas){


int iNou, jNou;

for (int dir = 0; dir<4; dir++){


iNou = i + vert[dir];
jNou = j + oriz[dir];
if (posibil(iNou,jNou)){
sol[iNou][jNou] = pas;
if (iNou == 0 || iNou == n-1 ||
jNou == 0 || jNou == m-1) scrie();
traseu(iNou,jNou,pas+1);
sol[iNou][jNou] = 0;
}
}
}

private void scrie(){


System.out.println("Solutia:"+ ++nrSol);
for (int i = 0; i<n; i++){
for (int j = 0;j<m; j++)
System.out.print(sol[i][j]+"\t");
ASD

System.out.println();
}
}

private boolean posibil(int lin, int col){


return (lin>=0 && lin<n &&
col>=0 && col<m &&
lab[lin][col]==1 && sol[lin][col] == 0);
}

public static void main (String []args){


int i=0;
int j=2;
Labirint labirint=new Labirint(i,j);
}
}

2. Colorarea hartilor

Fiind data o harta cu n tari, se cer toate posibilitatile de a colora o harta, utilizand 4 culori
(rosu,galben,verde,albastru) a.i, doua tari vecine sa nu fie colorate la fel. De exemplu, avem
urmatoarea harta cu 7 tari si o solutie posibila de colorare.

0 1
4
2 3
6
5

Harta este reprezentata cu ajutorul unei matrici patratice. Pentru fiecare linie i (reprezentand tara i)
avem j coloane (1 = daca se invecineaza cu tara j, 0 = daca nu se invecineaza cu tara j). Pentru
exemplul de mai sus avem urmatoarea matrice (va fi salvata intr-un fisier harta.in).

0,1,1,0,1,1,0
1,0,0,0,1,1,1
1,1,0,1,1,1,1
0,0,1,0,1,0,1
1,1,1,1,0,0,1
1,1,1,0,0,0,1
0,1,1,1,1,1,0

Rezultatul va fi salvat intr-un fisier harta.out si va fi codificat sub forma unui vector in care fiecare
element i va avea valoarea 1 (rosu), 2 (galben), 3(verde) sau 4 (albastru).

import java.util.*;

public class Colors{

Vector stiva;
static int n;
static boolean as,ev;
ASD

int [][] a ={{0,1,1,0,1,1,0},


{1,0,0,0,1,1,1},
{1,1,0,1,1,1,1},
{0,0,1,0,1,0,1},
{1,1,1,1,0,0,1}
{1,1,1,0,0,0,1}
{0,1,1,1,1,1,0}};

private void initS(){


stiva.addElement(new Integer(0));
}

private boolean succesor(){


boolean as=false;
Integer el = (Integer)stiva.elementAt(stiva.size()-1);
if(el.intValue() < 4){
as=true;
el = new Integer(el.intValue()+1);
stiva.setElementAt(el,stiva.size()-1);
}
return as;
}

private boolean valid(){


boolean ev=true;
Integer el0 = (Integer)stiva.elementAt(stiva.size()-1);
for( int i=0; i < stiva.size()-1; i++ ){
Integer el = (Integer)stiva.elementAt(i);
if( el0.intValue()==el.intValue() && a[i][stiva.size()-1]==1){
ev=false;
break;
}
}
return ev;
}

private boolean solutie(){


return ( stiva.size()==n );
}

private void tipar(){


for( int i=0;i < n;i++ ){
Integer el = (Integer)stiva.elementAt(i);
System.out.println("Tara="+i +" culoarea= " +
( el.intValue()+" "));
}
System.out.println("__________________\n");
}

private void backtracking(){


stiva = new Vector();
initS();
while( stiva.size()!=0 ){
do{
as=succesor();
if(as) ev=valid();
}
while((as)&&(!ev));

if(as){
if(solutie()) tipar();
else initS();
}
else stiva.removeElementAt( stiva.size()-1 );
}
ASD

System.out.println("Sfarsit generare");
}

public static void main(String []args){


n=7;
Colors p = new Colors();
p.backtracking();
}
}

3. Partitiile unui numar natural

Sa se afiseze toate modurile de descompunere a unui numar natural n ca suma de numere naturale.
import java.util.*;

public class Partitii{

Vector stiva;
static int n;
static boolean as,ev;

private void initS(){


stiva.addElement(new Integer(0));
}

private boolean succesor(){


boolean as=false;
Integer el = (Integer)stiva.elementAt(stiva.size()-1);
if(el.intValue() <= 4)
{
as=true;
el = new Integer(el.intValue()+1);
stiva.setElementAt(el,stiva.size()-1);
}
return as;
}

private boolean valid(){


boolean ev=true;
Integer el0 = (Integer)stiva.elementAt(stiva.size()-1);
int s=0;
for( int i=0; i < stiva.size()-1; i++ )
{

Integer el = (Integer)stiva.elementAt(i);
s+=el.intValue();
}
if(s>n)
{
ev=false;
}
return ev;
}

private boolean solutie(){


int s=0;
for( int i=0; i < stiva.size(); i++ ){
ASD

Integer el = (Integer)stiva.elementAt(i);
s+=el.intValue();
}

if(s==n) return true;


else return false;

private void tipar(){


for( int i=0;i < stiva.size()-1;i++ )
{
Integer el = (Integer)stiva.elementAt(i);
System.out.print(el.intValue()+"+");
}
Integer el_ultim = (Integer)stiva.elementAt(stiva.size()-1);
System.out.print(el_ultim.intValue());
System.out.println("\n");
}

private void backtracking(){


stiva = new Vector();
initS();
while( stiva.size()!=0 ){
do
{
as=succesor();
if(as) ev=valid();
}
while((as)&&(!ev));

if(as)
{
if(solutie()) tipar();
else initS();
}
else stiva.removeElementAt( stiva.size()-1 );
}
System.out.println("Sfarsit generare");
}

public static void main(String []args){


n=6;
Partitii p= new Partitii();
p.backtracking();
} //end main
}

4. Turneul calului pe tabla de sah

Fiind data o tabla de sah de dimensiune nxn si cunoscand pozitia unui cal , se cer toate posibilitatile
de a parcurge intreaga tabla , a.i calul sa nu treaca de doua ori prin acelasi loc. Solutiile gasite
pentru un anumit n trebuie salvate intr-un fisier pe disc.

import java.io.*;
class Calut{

static final int LIBER=0,SUCCES=1,ESEC=0,NMAX=8;


static final int[] a={0,2,1,-1,-2,-2,-1,1,2}; // miscari posibile pe Ox
static final int[] b={0,1,2,2,1,-1,-2,-2,-1}; // miscari posibile pe Oy
static int[][] tabla=new int[NMAX+1][NMAX+1]; // tabla de sah
static int n,np,ni=0; // np=n*n
ASD

public static void main(String[] args) throws IOException{

BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

// tabla de sah nu poate avea mai putin de 4 patratele


while ((n<3)||(n>NMAX)){
System.out.print("Dimensiunea tablei de sah (n>3): ");
n=Integer.parseInt(br.readLine());
}

np=n*n; //numar patratele

//initializare
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)
tabla[i][j]=LIBER;

//punct de plecare
tabla[1][1]=1;
if(incerc(2,1,1)==SUCCES) afisare();
else System.out.println("\nNu exista solutii !!!");
System.out.println("\n\nNumar de incercari = "+ni);
} // main

static void afisare(){


System.out.println("\r----------------------------------");

for(int i=1;i<=n;i++){
System.out.println();
for(int j=1;j<=n;j++)
System.out.print("\t"+tabla[i][j]);
}
}// afisare()

static int incerc(int i, int x, int y){


int xu,yu,k,rezultatIncercare;
ni++;
k=1;

rezultatIncercare=ESEC;
while ((rezultatIncercare==ESEC)&&(k<=8))// miscari posibile cal
{
xu=x+a[k]; //actualizare pozitie pe Ox
yu=y+b[k]; //actualizare pozitie pe Oy

// verificare
if((xu>=1)&&(xu<=n)&&(yu>=1)&&(yu<=n))
if(tabla[xu][yu]==LIBER){
tabla[xu][yu]=i;
afisare();

if (i<np){
rezultatIncercare=incerc(i+1,xu,yu);
if(rezultatIncercare==ESEC) tabla[xu][yu]=LIBER;
}
else rezultatIncercare=SUCCES;
}

k++;
}// while
return rezultatIncercare;
}// incerc()
}// class
ASD

5. Probleme propuse

5.1 Problema vecinilor

Un grup de n persoane sunt asezate pe un rand de scaune. Intre oricare doi vecini izbucnesc
conflicte. Rearanjati persoanele pe scaune astfel ıncat ıntre oricare doi vecini ”certati” sa existe una
sau cel mult doua persoane cu care nu au apucat sa se certe! Afisati toate variantele de reasezare
posibile.

Vom rezolva problema prin metada backtracking. Presupunem ca persoanele sunt numerotate la
ınceput, de la stanga la dreapta cu 1, 2, ..., n. Consideram ca solutie un vector x cu n componente
pentru care xi reprezinta ”pozitia pe care se va afla persoana i dupa reasezare”.

Pentru k > 1 dat, conditiile de continuare sunt:

a) xj ≠ xk, pentru j = 1, ..., k − 1 (x trebuie sa fie permutare)


b) |xk − xk−1| = 2 sau 3 (ıntre persoana k si vecinul sau anterior trebuie sa se afle una sau doua
persoane)

5.2 Problema parantezelor

Se da numarul natural n>0. Sa se determine toate sirurile de n paranteze rotunde care se inchid
corect. De exemplu, pentru n=4 avem : (()) si ()() . Solutiile gasite pentru un anumit n trebuie
salvate intr-un fisier pe disc.

5.3 Masa rotunda si regele Arthur

La curtea regelui Arthur sunt n cavaleri , fiecare avand dusmani. Pentru a pastra armonia la masa
rotunda , regele trebuie sa ii aseze la masa astfel incat doi dusmani sa nu fie vecini. Dusmanii sunt
specificati utilizand o matrice (elementul aij este 1 daca cavalerul i este dusmanit de cavalerul j , si
0 daca acestia sunt prieteni).

5.4 Tricolor

Avem la dispozitie 6 culori : alb , galben , rosu, verde , albastru , negru. Sa se gaseasca toate
drapelele tricolore ce se pot proiecta stiind ca cele trei culori de pe un drapel sunt distincte, iar
culoarea din mijloc trebuie sa fie pentru orice drapel galben sau verde.

S-ar putea să vă placă și