#include <cstdio>
#include <string>
#include <vector>
#include <ctime>
#include <cmath>
using namespace std;
int read( ) { int n; scanf ( "%d" , & n) ; return n; }
/*
* Polom diagramu przypisujemy identyfikatory (id) od 0 do 18.
* To będzie kolejność, w której będziemy wypełniać pola.
*
* 18 7 8
* 17 2 4 9
*16 1 0 5 10
* 15 3 6 11
* 14 13 12
*
*/
const int n = 19 ;
const int roznica = 5 ; // to minimalna różnica wartości w sąsiednich polach
int diagram[ n] ; // tu będziemy wpisywać wartości umieszczane w poszczególnych polach
// tutaj dla każdego pola umieszczamy listę pól-sąsiadów o mniejszych id
// każda lista zakończona jest wartością ujemną (-1)
int s0[ ] = { - 1 } ;
int s1[ ] = { 0 , - 1 } ;
int s2[ ] = { 0 , 1 , - 1 } ;
int s3[ ] = { 0 , 1 , - 1 } ;
int s4[ ] = { 0 , 2 , - 1 } ;
int s5[ ] = { 0 , 4 , - 1 } ;
int s6[ ] = { 0 , 3 , 5 , - 1 } ;
int s7[ ] = { 2 , 4 , - 1 } ;
int s8[ ] = { 4 , 7 , - 1 } ;
int s9[ ] = { 4 , 5 , 8 , - 1 } ;
int s10[ ] = { 5 , 9 , - 1 } ;
int s11[ ] = { 5 , 6 , 10 , - 1 } ;
int s12[ ] = { 6 , 11 , - 1 } ;
int s13[ ] = { 3 , 6 , 12 , - 1 } ;
int s14[ ] = { 3 , 13 , - 1 } ;
int s15[ ] = { 1 , 3 , 14 , - 1 } ;
int s16[ ] = { 1 , 15 , - 1 } ;
int s17[ ] = { 1 , 2 , 16 , - 1 } ;
int s18[ ] = { 2 , 7 , 17 , - 1 } ;
// tu definiujemy tablice tablica sąsiadów (powyższych list)
int * sasiad[ ] = { s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18} ;
// tu tablica, w której oznaczamy, czy dana wartość została już wpisana do diagramu (0 - nie wpisana, 1 - wpisana)
int wpisana[ n+ 1 ] ;
// te zmienne zliczają liczbę rozwiązań oraz liczbę wywołań funkcji rekurencyjnej
int liczbaRozwiazan;
int liczbaWywolanRekurencyjnych;
// przełącznik, do utożsamiania rozwiązań identycznych z punku widzenia symetrii i obrotów
const bool utozsamRozwiazania = false ;
//const bool utozsamRozwiazania = true;
// tu funkcja, która próbuje wypełnić pole o danym id kolejnymi wartościami od 1 do 19
// jeśli jakaś wartość nie pasuje, to jest pomijana
// jeśli wartość pasuje, to jest wpisywana i funkcja wywołuje się rekurencyjnie dla kolejnego id
// po sprawdzeniu wszystkich wartości funkcja kończy się, wtedy sterowanie wraca do funkcji o id mniejszym o jeden i tam jest próbowana kolejna wartość
// koniec wywałań rekurencyjnych następuje, gdy funkcja dostanie id = 19 - to oznacza, że diagram został poprawnie wypełniony
void wypelnij( int id)
{
liczbaWywolanRekurencyjnych++ ;
if ( id == n) { // mamy rozwiązanie
liczbaRozwiazan++ ;
// tu można jeszcze np. wypisać sobie rozwiązanie
return ;
}
for ( int x= 1 ; x<= n; ++ x) {
if ( wpisana[ x] == 1 ) continue ; // liczba x jest juz wpisana w inne pole diagramu, idziemy do następnego x
bool error = false ;
for ( int j= 0 ; sasiad[ id] [ j] >= 0 ; ++ j) {
if ( std:: abs ( x - diagram[ sasiad[ id] [ j] ] ) < roznica) { // std::abs zwraca wartość bezwzględną liczby
error = true ;
break ;
}
}
if ( error) continue ; // liczba x nie moze byc wpisana w pole id, bo jeden z sąsiadów ma już wpisaną wartość zbyt bliską wartości x, idziemy do następnego x
if ( utozsamRozwiazania) {
// ten warunek utożsamia obroty jako jedno rozwiązanie - tzn. zakładamy, że spośród sasiadów pola id=0 największą wartość ma pole id=1
if ( 2 <= id && id <= 6 ) if ( x > diagram[ 1 ] ) continue ;
// a ten warunek utożsamia odbicia symetryczne - tzn. zakładamy, że pole id=2 ma większą wartość niż pole id=3
if ( id == 3 ) if ( x > diagram[ 2 ] ) continue ;
}
// wartość x możemy wpisać w pole id
diagram[ id] = x; // wpisujemy liczbę x do diagramu
wpisana[ x] = 1 ; // oznaczamy wartość x jako wykorzystaną
wypelnij( id + 1 ) ; // przechodzimy rekurencyjnie do wypełniania kolejnego pola
wpisana[ x] = 0 ; // wymazujemy x z diagramu
// ... i sprawdzamy kolejną wartość x (w następnej iteracji pętli)
}
}
int main( )
{
time_t startTime = time ( NULL ) ;
liczbaRozwiazan = 0 ;
liczbaWywolanRekurencyjnych = 0 ;
for ( int x= 1 ; x<= n; ++ x) wpisana[ x] = 0 ;
wypelnij( 0 ) ;
time_t endTime = time ( NULL ) ;
printf ( "Liczba rozwiazan: %d\n " , liczbaRozwiazan) ;
printf ( "Liczba wywolan rekurencyjnych: %d\n " , liczbaWywolanRekurencyjnych) ;
printf ( "Czas dzialania programu (z dokladnoscia do 1 sekundy): %d sekund\n " , endTime - startTime) ;
return 0 ;
}
I2luY2x1ZGUgPGNzdGRpbz4KI2luY2x1ZGUgPHN0cmluZz4KI2luY2x1ZGUgPHZlY3Rvcj4KI2luY2x1ZGUgPGN0aW1lPgojaW5jbHVkZSA8Y21hdGg+CnVzaW5nIG5hbWVzcGFjZSBzdGQ7CgppbnQgcmVhZCgpIHsgaW50IG47IHNjYW5mKCIlZCIsICZuKTsgcmV0dXJuIG47IH0KCi8qCiAqICBQb2xvbSBkaWFncmFtdSBwcnp5cGlzdWplbXkgaWRlbnR5ZmlrYXRvcnkgKGlkKSBvZCAwIGRvIDE4LgogKiAgVG8gYsSZZHppZSBrb2xlam5vxZvEhywgdyBrdMOzcmVqIGLEmWR6aWVteSB3eXBlxYJuaWHEhyBwb2xhLgogKgogKiAgICAxOCAgIDcgICA4CiAqICAxNyAgIDIgICA0ICAgOQogKjE2ICAgMSAgIDAgICA1ICAxMAogKiAgMTUgICAzICAgNiAgMTEKICogICAgMTQgIDEzICAxMgogKgogKi8KCmNvbnN0IGludCBuID0gMTk7CmNvbnN0IGludCByb3puaWNhID0gNTsgLy8gdG8gbWluaW1hbG5hIHLDs8W8bmljYSB3YXJ0b8WbY2kgdyBzxIVzaWVkbmljaCBwb2xhY2gKaW50IGRpYWdyYW1bbl07IC8vIHR1IGLEmWR6aWVteSB3cGlzeXdhxIcgd2FydG/Fm2NpIHVtaWVzemN6YW5lIHcgcG9zemN6ZWfDs2xueWNoIHBvbGFjaAoKLy8gdHV0YWogZGxhIGthxbxkZWdvIHBvbGEgdW1pZXN6Y3phbXkgbGlzdMSZIHDDs2wtc8SFc2lhZMOzdyBvIG1uaWVqc3p5Y2ggaWQKLy8ga2HFvGRhIGxpc3RhIHpha2/FhGN6b25hIGplc3Qgd2FydG/Fm2NpxIUgdWplbW7EhSAoLTEpCmludCBzMFtdID0gey0xfTsKaW50IHMxW10gPSB7MCwgLTF9OwppbnQgczJbXSA9IHswLCAxLCAtMX07CmludCBzM1tdID0gezAsIDEsIC0xfTsKaW50IHM0W10gPSB7MCwgMiwgLTF9OwppbnQgczVbXSA9IHswLCA0LCAtMX07CmludCBzNltdID0gezAsIDMsIDUsIC0xfTsKaW50IHM3W10gPSB7MiwgNCwgLTF9OwppbnQgczhbXSA9IHs0LCA3LCAtMX07CmludCBzOVtdID0gezQsIDUsIDgsIC0xfTsKaW50IHMxMFtdID0gezUsIDksIC0xfTsKaW50IHMxMVtdID0gezUsIDYsIDEwLCAtMX07CmludCBzMTJbXSA9IHs2LCAxMSwgLTF9OwppbnQgczEzW10gPSB7MywgNiwgMTIsIC0xfTsKaW50IHMxNFtdID0gezMsIDEzLCAtMX07CmludCBzMTVbXSA9IHsxLCAzLCAxNCwgLTF9OwppbnQgczE2W10gPSB7MSwgMTUsIC0xfTsKaW50IHMxN1tdID0gezEsIDIsIDE2LCAtMX07CmludCBzMThbXSA9IHsyLCA3LCAxNywgLTF9OwoKLy8gdHUgZGVmaW5pdWplbXkgdGFibGljZSB0YWJsaWNhIHPEhXNpYWTDs3cgKHBvd3nFvHN6eWNoIGxpc3QpCmludCAqc2FzaWFkW10gPSB7IHMwLCBzMSwgczIsIHMzLCBzNCwgczUsIHM2LCBzNywgczgsIHM5LCBzMTAsIHMxMSwgczEyLCBzMTMsIHMxNCwgczE1LCBzMTYsIHMxNywgczE4fTsKCi8vIHR1IHRhYmxpY2EsIHcga3TDs3JlaiBvem5hY3phbXksIGN6eSBkYW5hIHdhcnRvxZvEhyB6b3N0YcWCYSBqdcW8IHdwaXNhbmEgZG8gZGlhZ3JhbXUgKDAgLSBuaWUgd3Bpc2FuYSwgMSAtIHdwaXNhbmEpCmludCB3cGlzYW5hW24rMV07CgovLyB0ZSB6bWllbm5lIHpsaWN6YWrEhSBsaWN6YsSZIHJvendpxIV6YcWEIG9yYXogbGljemLEmSB3eXdvxYJhxYQgZnVua2NqaSByZWt1cmVuY3lqbmVqCmludCBsaWN6YmFSb3p3aWF6YW47CmludCBsaWN6YmFXeXdvbGFuUmVrdXJlbmN5am55Y2g7CgovLyBwcnplxYLEhWN6bmlrLCBkbyB1dG/FvHNhbWlhbmlhIHJvendpxIV6YcWEIGlkZW50eWN6bnljaCB6IHB1bmt1IHdpZHplbmlhIHN5bWV0cmlpIGkgb2Jyb3TDs3cKY29uc3QgYm9vbCB1dG96c2FtUm96d2lhemFuaWEgPSBmYWxzZTsKLy9jb25zdCBib29sIHV0b3pzYW1Sb3p3aWF6YW5pYSA9IHRydWU7CgovLyB0dSBmdW5rY2phLCBrdMOzcmEgcHLDs2J1amUgd3lwZcWCbmnEhyBwb2xlIG8gZGFueW0gaWQga29sZWpueW1pIHdhcnRvxZtjaWFtaSBvZCAxIGRvIDE5Ci8vIGplxZtsaSBqYWthxZsgd2FydG/Fm8SHIG5pZSBwYXN1amUsIHRvIGplc3QgcG9taWphbmEKLy8gamXFm2xpIHdhcnRvxZvEhyBwYXN1amUsIHRvIGplc3Qgd3Bpc3l3YW5hIGkgZnVua2NqYSB3eXdvxYJ1amUgc2nEmSByZWt1cmVuY3lqbmllIGRsYSBrb2xlam5lZ28gaWQKLy8gcG8gc3ByYXdkemVuaXUgd3N6eXN0a2ljaCB3YXJ0b8WbY2kgZnVua2NqYSBrb8WEY3p5IHNpxJksIHd0ZWR5IHN0ZXJvd2FuaWUgd3JhY2EgZG8gZnVua2NqaSBvIGlkIG1uaWVqc3p5bSBvIGplZGVuIGkgdGFtIGplc3QgcHLDs2Jvd2FuYSBrb2xlam5hIHdhcnRvxZvEhwovLyBrb25pZWMgd3l3YcWCYcWEIHJla3VyZW5jeWpueWNoIG5hc3TEmXB1amUsIGdkeSBmdW5rY2phIGRvc3RhbmllIGlkID0gMTkgLSB0byBvem5hY3phLCDFvGUgZGlhZ3JhbSB6b3N0YcWCIHBvcHJhd25pZSB3eXBlxYJuaW9ueQoKdm9pZCB3eXBlbG5paihpbnQgaWQpCnsKICAgIGxpY3piYVd5d29sYW5SZWt1cmVuY3lqbnljaCsrOwoKICAgIGlmIChpZCA9PSBuKSB7IC8vIG1hbXkgcm96d2nEhXphbmllCiAgICAgICAgbGljemJhUm96d2lhemFuKys7CiAgICAgICAgLy8gdHUgbW/FvG5hIGplc3pjemUgbnAuIHd5cGlzYcSHIHNvYmllIHJvendpxIV6YW5pZQogICAgICAgIHJldHVybjsKICAgIH0KCiAgICBmb3IgKGludCB4PTE7IHg8PW47ICsreCkgewoKICAgICAgICBpZiAod3Bpc2FuYVt4XSA9PSAxKSBjb250aW51ZTsgLy8gbGljemJhIHggamVzdCBqdXogd3Bpc2FuYSB3IGlubmUgcG9sZSBkaWFncmFtdSwgaWR6aWVteSBkbyBuYXN0xJlwbmVnbyB4CgogICAgICAgIGJvb2wgZXJyb3IgPSBmYWxzZTsKICAgICAgICBmb3IgKGludCBqPTA7IHNhc2lhZFtpZF1bal0gPj0gMDsgKytqKSB7CiAgICAgICAgICAgIGlmIChzdGQ6OmFicyh4IC0gZGlhZ3JhbVtzYXNpYWRbaWRdW2pdXSkgPCByb3puaWNhKSB7IC8vIHN0ZDo6YWJzIHp3cmFjYSB3YXJ0b8WbxIcgYmV6d3pnbMSZZG7EhSBsaWN6YnkKICAgICAgICAgICAgICAgIGVycm9yID0gdHJ1ZTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmIChlcnJvcikgY29udGludWU7IC8vIGxpY3piYSB4IG5pZSBtb3plIGJ5YyB3cGlzYW5hIHcgcG9sZSBpZCwgYm8gamVkZW4geiBzxIVzaWFkw7N3IG1hIGp1xbwgd3Bpc2FuxIUgd2FydG/Fm8SHIHpieXQgYmxpc2vEhSB3YXJ0b8WbY2kgeCwgaWR6aWVteSBkbyBuYXN0xJlwbmVnbyB4CgogICAgICAgIGlmICh1dG96c2FtUm96d2lhemFuaWEpIHsKICAgICAgICAgICAgLy8gdGVuIHdhcnVuZWsgdXRvxbxzYW1pYSBvYnJvdHkgamFrbyBqZWRubyByb3p3acSFemFuaWUgLSB0em4uIHpha8WCYWRhbXksIMW8ZSBzcG/Fm3LDs2Qgc2FzaWFkw7N3IHBvbGEgaWQ9MCBuYWp3acSZa3N6xIUgd2FydG/Fm8SHIG1hIHBvbGUgaWQ9MQogICAgICAgICAgICBpZiAoMiA8PSBpZCAmJiBpZCA8PSA2KSBpZiAoeCA+IGRpYWdyYW1bMV0pIGNvbnRpbnVlOwogICAgICAgICAgICAvLyBhIHRlbiB3YXJ1bmVrIHV0b8W8c2FtaWEgb2RiaWNpYSBzeW1ldHJ5Y3puZSAtIHR6bi4gemFrxYJhZGFteSwgxbxlIHBvbGUgaWQ9MiBtYSB3acSZa3N6xIUgd2FydG/Fm8SHIG5pxbwgcG9sZSBpZD0zCiAgICAgICAgICAgIGlmIChpZCA9PSAzKSBpZiAoeCA+IGRpYWdyYW1bMl0pIGNvbnRpbnVlOwogICAgICAgIH0KCiAgICAgICAgLy8gd2FydG/Fm8SHIHggbW/FvGVteSB3cGlzYcSHIHcgcG9sZSBpZAogICAgICAgIGRpYWdyYW1baWRdID0geDsgLy8gd3Bpc3VqZW15IGxpY3pixJkgeCBkbyBkaWFncmFtdQogICAgICAgIHdwaXNhbmFbeF0gPSAxOyAvLyBvem5hY3phbXkgd2FydG/Fm8SHIHggamFrbyB3eWtvcnp5c3RhbsSFCiAgICAgICAgd3lwZWxuaWooaWQgKyAxKTsgLy8gcHJ6ZWNob2R6aW15IHJla3VyZW5jeWpuaWUgZG8gd3lwZcWCbmlhbmlhIGtvbGVqbmVnbyBwb2xhCiAgICAgICAgd3Bpc2FuYVt4XSA9IDA7IC8vIHd5bWF6dWplbXkgeCB6IGRpYWdyYW11CiAgICAgICAgLy8gLi4uIGkgc3ByYXdkemFteSBrb2xlam7EhSB3YXJ0b8WbxIcgeCAodyBuYXN0xJlwbmVqIGl0ZXJhY2ppIHDEmXRsaSkKICAgIH0KfQoKaW50IG1haW4oKQp7CiAgICB0aW1lX3Qgc3RhcnRUaW1lID0gdGltZShOVUxMKTsKCiAgICBsaWN6YmFSb3p3aWF6YW4gPSAwOwogICAgbGljemJhV3l3b2xhblJla3VyZW5jeWpueWNoID0gMDsKICAgIGZvciAoaW50IHg9MTsgeDw9bjsgKyt4KSB3cGlzYW5hW3hdID0gMDsKCiAgICB3eXBlbG5paigwKTsKCiAgICB0aW1lX3QgZW5kVGltZSA9IHRpbWUoTlVMTCk7CgogICAgcHJpbnRmKCJMaWN6YmEgcm96d2lhemFuOiAlZFxuIiwgbGljemJhUm96d2lhemFuKTsKICAgIHByaW50ZigiTGljemJhIHd5d29sYW4gcmVrdXJlbmN5am55Y2g6ICVkXG4iLCBsaWN6YmFXeXdvbGFuUmVrdXJlbmN5am55Y2gpOwogICAgcHJpbnRmKCJDemFzIGR6aWFsYW5pYSBwcm9ncmFtdSAoeiBkb2tsYWRub3NjaWEgZG8gMSBzZWt1bmR5KTogJWQgc2VrdW5kXG4iLCBlbmRUaW1lIC0gc3RhcnRUaW1lKTsKCiAgICByZXR1cm4gMDsKfQoKCg==