#include #include #include #include #include #include #define KYBLU 5 #define NAVSTIV(arg1, arg2) navstiveno[map(arg1)] = &navstiveno[map(arg2)] #define NOVY(arg1) navstiveno[map(arg1)] == 0 int objem[KYBLU], nasobky[KYBLU], cil[KYBLU], kyblooperaci; void **navstiveno; static int map(int vect[KYBLU]) { int rtn = 0, i; for( i = 0; i < KYBLU; i++ ) rtn += vect[i] * nasobky[i]; return rtn; } static int *unmap(int stav) { static int vect[KYBLU]; int i; for( i = KYBLU - 1; i >= 0; i--) vect[i] = stav / nasobky[i], stav %= nasobky[i]; return vect; } /// Akce s kybli ///////////////////////////////////////////// static inline void prelej(int *stav, int co, int kam) { int volno = objem[kam] - stav[kam]; kyblooperaci++; if( volno > stav[co] ){ stav[kam] += stav[co]; stav[co] = 0; } else { stav[kam] = objem[kam]; stav[co] -= volno; } } static inline void napln(int *stav, int co) { kyblooperaci++; stav[co] = objem[co]; } static inline void vylej(int *stav, int co) { kyblooperaci++; stav[co] = 0; } ///////////////////////////////////////////////////////////// /// Operace se stavy //////////////////////////////////////////////////////////////////////////// #define zarad_stav(stav) do { \ if( NOVY(stav) ){ \ nalezeno++; \ if( memcmp( stav, cil, sizeof(int)*KYBLU) == 0 ) \ goto nalezeno; \ fronta.push( stav ); \ NAVSTIV( stav, zpracuj ); \ stav = (int*)malloc(sizeof(int)*KYBLU); \ } } while (0) static void print_stav(int *stav){ int i; printf("("); for( i = 0; i < KYBLU -1; i++ ) printf("%d ", stav[i]); printf("%d) ", stav[i]); } static int vypis_cestu(void **stav){ int rtn = 0; if( *stav != (void*)stav ) rtn = vypis_cestu ((void**)*stav); return rtn + 1; } ///////////////////////////////////////////////////////////////////////////////////////////////////// #define MOZNOSTI 10 int moznosti[5][10] = { { 3, 4, 5, 6, 7, 10, 14, 19, 25, 31 }, { -2, -1, 0, 1, 2, 3, 4, 5, 7, 10 }, { -2, -1, 0, 1, 2, 3, 4, 5, 7, 10 }, { 0, 1, 2, 3, 4, 5, 7, 10, 14, 18 }, { 0, 1, 2, 3, 4, 5, 7, 10, 14, 18 }, }; int konstanty[5]; #define K(arg) (moznosti[arg][konstanty[arg]]) #define P(arg) for( konstanty[arg] = 0; konstanty[arg] < MOZNOSTI; konstanty[arg]++ ) #define PERMUTUJ P(0){P(1){P(2){P(3){P(4) #define JUTUMREP }}}} static int ohodnod(const int *stav){ int cena = 0, i, j; for( i = 0; i < KYBLU; i++ ){ if( stav[i] == cil[i] ) cena += K(0); else if( stav[i] == 0 ) cena -= K(1); else if( stav[i] == objem[i] ) cena -= K(2); for( j = 0; j < KYBLU; j++ ){ if( stav[i] == cil[j] ) cena += K(3); if( i != j ){ if(stav[j] + stav[i] == cil[i] || stav[j] + stav[i] == cil[j]) cena += K(4); if(stav[i] - objem[i] == cil[j] - stav[j] || stav[j] - objem[j] == cil[i] - stav[i] ) cena += K(4); } } } return cena; } class porovnej { public: bool operator()(const int* stav1, const int* stav2) const { int c1 = ohodnod(stav1), c2 = ohodnod(stav2); if( c1 == c2 ) return stav2 > stav1; return c1 < c2; } }; ////////////////////////////////////////////////////////////////////////////////////////////////////// int main(int argc, char *argv[]) { int start[KYBLU], *stav, i, j, instance; for( i = 0; i < KYBLU; i++ ) // Nacti objemy scanf("%d", objem + i); for( i = 1, nasobky[0] = 1; i < KYBLU; i++ ) // Spocti nasobky nasobky[i] = nasobky[i-1] * (objem[i-1]+1); for( i = 0; i < KYBLU; i++ ) // Nacti start scanf("%d", start + i); instance = 0; navstiveno = (void**)malloc(sizeof(void*)*(map(objem)+1)); // Inicializace "grafu" if( navstiveno == NULL ) printf("Error\n"); stav = (int*)malloc( sizeof(int)*KYBLU ); while(1){ instance++; for( i = 0; i < KYBLU; i++ ) // Nacteni cile if( scanf("%d", cil + i) != 1) goto exit; PERMUTUJ{ std::priority_queue,porovnej> fronta; int *zpracuj, nalezeno = 0; kyblooperaci = 0; memset(navstiveno, 0, sizeof(void*)*(map(objem)+1)); memcpy(stav, start, sizeof(int)*KYBLU); zpracuj = start; zarad_stav(stav); while( !fronta.empty() ){ zpracuj = fronta.top(); fronta.pop(); // Generuj stavy for( i = 0; i < KYBLU; i++ ){ for( j = 0; j < KYBLU; j++ ){ // Prelej if( i == j || zpracuj[i] == 0 ) continue; memcpy(stav, zpracuj, sizeof(int)*KYBLU); prelej(stav, i, j); zarad_stav(stav); } // Napln memcpy(stav, zpracuj, sizeof(int)*KYBLU); napln(stav, i); zarad_stav(stav); // Vylej memcpy(stav, zpracuj, sizeof(int)*KYBLU); vylej(stav, i); zarad_stav(stav); } free(zpracuj); } printf("\nNenalezeno\n"); continue; nalezeno: NAVSTIV( stav, zpracuj ); i = vypis_cestu( (void**)&navstiveno[map(cil)] ); printf("%d: [%d %d %d %d %d] %d\t%d\t%d\t%d\n", instance, K(0), K(1), K(2), K(3), K(4), fronta.size(), nalezeno, kyblooperaci, i ); while( !fronta.empty() ){ free( fronta.top() ); fronta.pop(); } // Smazu frontu free(zpracuj); } JUTUMREP } exit: free(navstiveno); free(stav); return 0; }