Muszę napisać program "obliczający" wieże Hanoi iteracyjnie. Tak, program na zaliczenie. Algorytm napisałem na podstawie wikipedii:
- przenieś najmniejszy krążek na kolejny (*) słupek.
- wykonaj jedyny możliwy do wykonania ruch, nie zmieniając położenia krążka najmniejszego
- powtarzaj punkty 1 i 2, aż do odpowiedniego ułożenia wszystkich krążków.
(*) Kolejny słupek wyznaczamy w zależności od liczby krążków. Jeśli liczba krążków jest parzysta, kolejnym słupkiem jest ten po prawej stronie (gdy dojdziemy do słupka C w następnym ruchu używamy słupka A). Natomiast jeśli liczba krążków jest nieparzysta, kolejnym słupkiem jest ten po lewej stronie (gdy dojdziemy do słupka A w następnym ruchu używamy słupka C)
Ok, super, wszystko działa. Dla 3 krążków i 3 drążków, program wykonuje się w 7 ruchach, czyli optymalnie. Problem pojawia się, gdy jest tego więcej.
Przy 4 drążkach i 4 krążkach, program nie wykonuje się nawet pomimo 150 000 ruchów.
Przy 3 drążkach i 4 krążkach, przy 5000 ruchach jeszcze się nie wykona, przy 10 000 już tak.
Co jest grane? Można to jakoś zoptymalizować?
Program jest wykonany na listach w taki sposób:
//- elementy listy są drążkami
- każdy element posiada tablice krążków
- tablica [0, 0, 0, 0] (dla 4 krążków) oznacza brak krążków na drążku
- tablica [1, 2, 0, 0] oznacza że na drążku są krążki 1 i 2 (1 jest na krążku 2gim)//
Wkleję tylko funkcję odpowiedzialną na przenoszenie krążków:
void hanoi(rod **head, rod **tail)
{
rod *temp, *temp2;
int flag = 0, div = 0;
for(int i = 0; i < 5000; i++)
{
temp = *head;
flag = 0;
if(div % 2 == 0) // move smallest disk to the right if odd, or left if even
{
while(temp != NULL)
{
if(flag == 1)
{
push(1, &temp->disks);
break;
}
if(temp->disks[0] == 1 && flag == 0)
{
pop(&temp->disks);
flag = 1;
}
if(n % 2 == 0)
{
if(temp->next == NULL && flag == 1)
{
temp = *head;
}
else
{
temp = temp->next;
}
}
else
{
if(temp->prev == NULL)
{
temp = *tail;
}
else
{
temp = temp->prev;
}
}
}
}
else // make first possible move
{
while(temp != NULL && flag == 0)
{
temp2 = *head;
while(temp2 != NULL && flag == 0)
{
if((temp->disks[0] < temp2->disks[0] || temp2->disks[0] == 0) && temp->disks[0] != 1 && temp2->disks[0] != 1 && temp->disks[0] != 0 && temp->num != temp2->num)
{
int t = temp->disks[0];
pop(&temp->disks);
push(t, &temp2->disks);
flag = 1;
}
temp2 = temp2->next;
}
temp = temp->next;
}
}
div++;
}
}
Wszystkie sugestie będą mile widziane :D Siedzę nad tym cały weekend i nie wiem co z tym można zrobić.