Cum să obțineți în jurul valorii de tabla de șah cal, fără a merge pe orice domeniu de două ori și a reveni la celula inițială?
Destul de bună dreptate, expresia „curs de cal“ înseamnă limba română este foarte inteligent și ideea trivial. Că centrele de sarcina pervazuri este nuca destul de greu pentru a sparge, care se rupe dinții chiar și unii profesioniști. Nu, desigur, găsi unele o rundă nu este atât de dificil. De exemplu, puteți desena cu ușurință pe hârtie de bypass traseu panouri de cai 4x4, iar apoi pauza 4 a traseului în apropierea centrului de bord și lipiți-le de la o rută. Există o altă metodă cunoscută, de by-pass primul „franjuri“ lățime a plăcii în două celule, și apoi - 16 celule centrale.
Dar am fost interesat de această poveste (și se întreba întotdeauna) este realizarea unei anumite eludare a constatat practic de mână, și cu totul altceva. De exemplu, să ocol a început deja - calul a vizitat deja de mai multe celule. Putem termina acest turneu? Dacă da, cum să procedeze? Este evident că aici problema nu depinde de dimensiunea specială și chiar forma de bord. Exact aceeași problemă poate fi pus pe un grafic complet arbitrar. Singurul lucru pe care vrem aici de cal și de bord - este de a ști care celulele calului sunt „adiacente“, și ceea ce - nu.
Asta e doar în această sarcină, o listă completă a tuturor opțiunilor disponibile, chiar și pentru computerele de astăzi, deci va trebui să caute alte căi. De fapt, idei bune au fost mult timp cunoscute. De exemplu, știm regula: calul trebuie să sari întotdeauna la celula, pentru care numărul de posibile mișcări cu acesta este cel mai mic. Și dacă există mai multe celule? Nu există nici o singură rețetă, după cum puteți vedea, nu există nici o ...
Aici puteți cumpăra chiar și un program de-a gata soluție în Pascal. Dar mai interesant de a face cu algoritmul în sine.
Cum de a rezolva problema de orb Panov - un truc mnemonic!
Algoritmi de matematică discrete pentru această problemă - ciclu shamiltonov și dincolo.
O regulă care, aparent, este justificată în practică, dar în teorie nu a fost încă confirmată este următoarea: de fiecare dată când mergem cal înapoi în cazul în care amenință cel mai mic număr nu a fost încă adoptată de către celule.
O altă modalitate este de a găsi o cale pe jumătate bord, simetric duplica-l și conectarea ambelor rute.
Original oferă de obicei un timp liniar placi algoritm pervazuri. A fost sugerat Varnsdorf (warnsdorff) în 1983.
Regula este formulată foarte simplu: următoarea mutare calul pentru a face o celulă în cazul în care există cele mai puține mișcări posibile. În cazul în care același număr de celule muta mai mult, puteți alege orice.
În practică, acest lucru se realizează, de exemplu, după cum urmează. Înainte de fiecare muta rating evaluat cel mai apropiat cal domenii disponibile - domenii în care calul nu a fost încă, și el se poate deplasa într-o tură. câmp Rating-ul este determinat de numărul de câmpuri disponibile de lângă ea. Este mai mic rating, cu atât mai bine este. Apoi a făcut progrese pe teren, cu cel mai mic rating (pe oricare dintre acestea, în cazul în care mai mult de unul), și așa mai departe până când nu există în cazul în care pentru a merge.
Euristici sunt întotdeauna de lucru pe panourile de la 5x5 până la 76x76 celule pentru mari dimensiuni bord cal poate veni la un impas. În plus, în funcție de regula algoritmului nu oferă toate soluțiile posibile (de exemplu, piese de cai), puteți merge împotriva regulilor și a obține încă o sarcină rundă satisfăcătoare.
Există un algoritm liniar pentru placi de orice dimensiune care împarte placa în bucăți mai mici, dar, din cauza abundenței de cazuri speciale, este destul de complicat și nu la fel de interesant ca acest euristică elegant.
Un alt mod de rezolvare a problemei este, în mod evident, în bustul cu retragere. Următoarea ilustrație este dată să se apropie de 8x8 bord.
Folosind două rânduri dimensionale matrice [64] și col [64] pentru stocarea numerele rândurilor, respectiv, și coloanele care succesiv calul trece bord.
Calul, care se află în poziția (i, j), se pot deplasa de lângă a fi în celule cu coordonate (i-2, j + 1), (i-1, j + 2), (i + 1, j + 2), ( i + 2 j + 1), (i + 2 j-1), (i + 1, j-2), (i-1, j-2), (i-2, j-1). Rețineți că, în cazul în care calul este aproape de marginea de bord, unele mișcări pot provoca mișcarea calului dincolo de faptul că, desigur, inacceptabilă. Opt posibil cal deplasările pot fi prezentate sub forma a două matrice ktmov1 [] și ktmov2 [], așa cum sa demonstrat în următorul fragment de program.
Prin urmare, cal, situat la poziția (i, j) se poate deplasa într-o poziție (i + ktmov [k], j + ktmov2 [k]), unde k - orice valoare în intervalul 0 - 7 ales dintre condițiile că calul trebuie să rămână pe bord. Astfel, programul care implementează mișcarea calului, în conformitate cu condițiile de mai sus vor fi după cum urmează:
int arr [8] [8], rândul [64], col [64];
int ktmov1 [8] = <-2, -1, 1, 2, 2, 1, -1, -2>;
int ktmov2 [8] = <1, 2, 2, 1, -1, -2, -2, -1>;
int i, j, move_num, d;
addknight () registru int a, b, e;
/ * Marcați celula ca o vizită și amintiți-vă coordonatele celulei * /
arr [i] [j] = 1;
rândul [move_num] = i;
col [move_num] = j;
move_num ++;
/ * Verificați posibila mișcare a calului 8 * /
pentru (a = 0; o <= 7 ; a++ ) /* если все ходы сделаны, печатаем их */
if (move_num> = 64) writeboard ();
exit (0);
>
/ * Definiți coloane și rânduri pentru următorul viraj * /
b = i + ktmov1 [a];
e = j + ktmov2 [a];
/ * Verificați că după operația de cezariană care rulează cal rămâne pe tabla de șah * /
în cazul în care (b <0 || b> 7 || e <0 || e> 7)
continua;
/ * Verificați pentru a vedea dacă am fost deja în celula * /
if (arr [b] [e] == 1)
continua;
i = b; j = e;
addknight ();
>
/ * Reducerea contorul de accident vascular cerebral și să încerce să facă următoarea mișcare * /
move_num--;
/ * Eliberați celula ocupată anterior de cal * /
arr [rândul [move_num]] [col [move_num]] = 0;
move_num--; / * Încercați să facă următoarea mișcare * /
i = rândul [move_num]; j = col [move_num];
move_num ++;
>
writeboard () int a;
clrscr ();
gotoxy (1, 10);
printf ( „Hit orice tastă pentru următoarea mișcare“);
gotoxy (1, 11);
pentru (a = 0; o <= 63 ; a++ ) if ( a % 8 == 0 )
printf ( "\ n");
printf ( "#");
>
pentru (a = 0; o lt; = 63; a ++) gotoxy (col [a] * 3 + 1, 12 + rd [a]);
printf ( "% 3d", a + 1);
getch ();
>
>