/eps/mac0122_algoritmos/ep3/oldresta.c

https://github.com/henriquegemignani/ime · C · 383 lines · 336 code · 19 blank · 28 comment · 112 complexity · 073531ec9dedc600ed0db7f768bd5986 MD5 · raw file

  1. /* ime2009bcc
  2. 5s7B2P0k */
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. /* Definição de constantes */
  6. #define PILHA_INIC_SIZE 32
  7. #define DIR_CIMA 1
  8. #define DIR_DIREITA 2
  9. #define DIR_BAIXO 3
  10. #define DIR_ESQUERDA 4
  11. /* easter egg */
  12. #define GOKU_POWER_LEVEL 9001
  13. int VERBOSE = 0;
  14. /* Matriz é dada por MATRIZ[LINHA][COLUNA]
  15. Geralmente, X ou I é utilizado para armazenar a LINHA,
  16. enquanto Y ou J para a COLUNA. */
  17. void masterError( char* str ) {
  18. printf("%s\n",str);
  19. exit(1);
  20. }
  21. #define getBit(t,i) ( ( (t) & (1 << (i)) ) != 0 )
  22. struct pontoData {
  23. int x, y;
  24. };
  25. typedef struct pontoData* ponto;
  26. ponto createPonto( int x, int y ) {
  27. ponto p = malloc( sizeof(struct pontoData) );
  28. if( !p ) masterError("Impossivel alocar memória para um novo ponto.");
  29. p->x = x;
  30. p->y = y;
  31. return p;
  32. }
  33. void copiaValoresPonto( ponto target, ponto source ) {
  34. target->x = source->x;
  35. target->y = source->y;
  36. }
  37. /*=======================================*/
  38. /* Funções relacionadas à estrutura item */
  39. struct itemData {
  40. ponto p;
  41. char dir;
  42. };
  43. typedef struct itemData* item;
  44. item createItem( int x, int y, char dir ) {
  45. item it = malloc( sizeof(struct itemData) );
  46. if( !it ) masterError("Impossivel alocar memória para um novo item.");
  47. it->p = createPonto( x, y );
  48. it->dir = dir;
  49. return it;
  50. }
  51. void copiaValoresItem( item target, item source ) {
  52. target->p->x = source->p->x;
  53. target->p->y = source->p->y;
  54. target->dir = source->dir;
  55. }
  56. item cloneItem( item it ) {
  57. item clone = createItem( -1, -1, 0 );
  58. copiaValoresItem( clone, it );
  59. return clone;
  60. }
  61. void limpaItem( item *it ) {
  62. free( (*it)->p );
  63. free( *it );
  64. *it = NULL;
  65. }
  66. /*=======================================*/
  67. /* Funções relacionadas à pilha */
  68. struct pilhaStr {
  69. item* vetor;
  70. item** permVect;
  71. int* permSize;
  72. int topo, tamanho;
  73. };
  74. typedef struct pilhaStr* pilha;
  75. pilha criaPilha( int tamanhoInic ) {
  76. pilha p = malloc( sizeof(struct pilhaStr) );
  77. if( !p ) masterError("Impossivel alocar memória para a pilha.\n");
  78. /* Vetor da Pilha */
  79. p->vetor = malloc( tamanhoInic * sizeof(item) );
  80. if( !p->vetor ) masterError("Impossivel alocar memória para o vetor da pilha.\n");
  81. /* Matriz de acoes invalidas */
  82. p->permVect = malloc( tamanhoInic * sizeof(item*) );
  83. if( !p->permVect ) masterError("Impossivel alocar memória para a matriz da pilha.\n");
  84. /* Vetor com o tamanho de cada linha da matriz de acoes invalidas */
  85. p->permSize = malloc( tamanhoInic * sizeof(int) );
  86. if( !p->permSize ) masterError("Impossivel alocar memória para a vetor do tamanho da matriz da pilha.\n");
  87. int i;
  88. for( i = 0; i < tamanhoInic; i++ ) {
  89. p->vetor[i] = createItem( -1, -1, 0 ); /* A pilha em si */
  90. p->permVect[i] = malloc( sizeof(item) ); /* Cada linha da matriz de acoes invalidas */
  91. if( !p->permVect[i] ) masterError("Impossivel alocar linha da matriz da pilha.");
  92. p->permVect[i][0] = createItem( -1, -1, 0 );
  93. p->permSize[i] = 1;
  94. }
  95. p->topo = 0;
  96. p->tamanho = tamanhoInic;
  97. return p;
  98. }
  99. void empilha( pilha p, item it ) {
  100. int i;
  101. if( p->topo == p->tamanho ) { /* aumentar vetor da pilha */
  102. i = p->tamanho;
  103. p->tamanho *= 2;
  104. item* aux = realloc( p->vetor, p->tamanho * sizeof(item) );
  105. if( !aux ) masterError("Impossivel alocar memória para expandir o vetor da pilha.\n");
  106. p->vetor = aux;
  107. for( ; i < p->tamanho; i++ ) {
  108. p->vetor[i] = createItem( -1, -1, 0 ); /* A pilha em si */
  109. p->permVect[i] = malloc( sizeof(item) ); /* Cada linha da matriz de acoes invalidas */
  110. if( !p->permVect[i] ) masterError("Impossivel alocar linha da matriz da pilha.");
  111. p->permVect[i][0] = createItem( -1, -1, 0 );
  112. p->permSize[i] = 1;
  113. }
  114. if( VERBOSE ) printf("Aumentou tamanho da pilha para %d\n", p->tamanho);
  115. }
  116. copiaValoresItem( p->vetor[p->topo], it );
  117. for( i = 0; i < p->permSize[p->topo]; i++ )
  118. limpaItem( &p->permVect[p->topo][i] );
  119. p->permVect[p->topo][0] = createItem( -1, -1, 0 );
  120. p->permSize[p->topo] = 1;
  121. p->topo++;
  122. }
  123. void desempilha( pilha p ) {
  124. p->topo--;
  125. }
  126. item topoPilha( pilha p ) {
  127. return p->vetor[p->topo-1];
  128. }
  129. char pilhaVazia( pilha p ) {
  130. return (p->topo == 0);
  131. }
  132. /*===============================*/
  133. void adcionaAcaoErrada( pilha p, ponto tar, char dir ) {
  134. if( pilhaVazia( p ) ) return; /* Chamada Invalida. */
  135. int cur = p->topo - 1, i;
  136. for( i = 0; i < p->permSize[cur] && ( p->permVect[cur][i]->dir != 0 ); i++ );
  137. if( i == p->permSize[cur] ) {
  138. p->permSize[cur] *= 2;
  139. item* aux = realloc( p->permVect[cur], p->permSize[cur] * sizeof(item) );
  140. if( !aux ) masterError("Impossivel alocar memória para expandir uma linha da matriz da pilha.\n");
  141. p->permVect[cur] = aux;
  142. /* iniciliza o resto */
  143. int j;
  144. for( j = i; j < p->permSize[cur]; j++ )
  145. p->permVect[cur][j] = createItem( -1, -1, 0 );
  146. }
  147. copiaValoresPonto( p->permVect[cur][i]->p, tar );
  148. p->permVect[cur][i]->dir = dir;
  149. }
  150. char isAcaoErrada( pilha p, ponto tar, char dir ) {
  151. int i, cur = p->topo - 1;
  152. if( cur < 0 ) return 0;
  153. for( i = 0; i < p->permSize[cur]; i++ ) {
  154. if( dir == p->permVect[cur][i]->dir && tar->x == p->permVect[cur][i]->p->x && tar->y == p->permVect[cur][i]->p->y )
  155. return 1;
  156. }
  157. return 0;
  158. }
  159. /*=======================================*/
  160. /* Declaração de variáveis globais */
  161. unsigned short int TAMANHO_X_MATRIZ = 7, TAMANHO_Y_MATRIZ = 7;
  162. char **pecas;
  163. unsigned int numPecas = 0, numBuracos = 0;
  164. unsigned long long numIteracoes = 0;
  165. /* PILHA */
  166. pilha respPilha;
  167. /*=======================================*/
  168. /* Codigo para resolução do problema */
  169. /* Dado as coordenadas (X,Y) de um valor da matriz global "pecas" e uma direção DIR,
  170. devolve 1 se é possivel fazer uma jogada no ponto dado com a direção dada,
  171. e 0 caso contrário. */
  172. char acaoValida( ponto p, char dir ) {
  173. int x = p->x, y = p->y;
  174. switch( dir ) {
  175. case DIR_CIMA:
  176. if( y < 2 || pecas[y - 2][x] != 1 || pecas[y - 1][x] != 1 || pecas[y][x] != 0 )
  177. return 0;
  178. return 1;
  179. case DIR_DIREITA:
  180. if( x > TAMANHO_X_MATRIZ - 3 || pecas[y][x + 2] != 1 || pecas[y][x + 1] != 1 || pecas[y][x] != 0 )
  181. return 0;
  182. return 1;
  183. case DIR_BAIXO:
  184. if( y > TAMANHO_Y_MATRIZ - 3 || pecas[y + 2][x] != 1 || pecas[y + 1][x] != 1 || pecas[y][x] != 0 )
  185. return 0;
  186. return 1;
  187. case DIR_ESQUERDA:
  188. if( x < 2 || pecas[y][x - 2] != 1 || pecas[y][x - 1] != 1 || pecas[y][x] != 0 )
  189. return 0;
  190. return 1;
  191. }
  192. return 0;
  193. }
  194. void realizaAcao( int x, int y, char dir ) {
  195. numPecas--;
  196. numBuracos++;
  197. switch( dir ) {
  198. case DIR_CIMA:
  199. pecas[y][x] = 1;
  200. pecas[y - 1][x] = 0;
  201. pecas[y - 2][x] = 0;
  202. return;
  203. case DIR_DIREITA:
  204. pecas[y][x] = 1;
  205. pecas[y][x + 1] = 0;
  206. pecas[y][x + 2] = 0;
  207. return;
  208. case DIR_BAIXO:
  209. pecas[y][x] = 1;
  210. pecas[y + 1][x] = 0;
  211. pecas[y + 2][x] = 0;
  212. return;
  213. case DIR_ESQUERDA:
  214. pecas[y][x] = 1;
  215. pecas[y][x - 1] = 0;
  216. pecas[y][x - 2] = 0;
  217. return;
  218. }
  219. }
  220. void desfazAcao( int x, int y, char dir ) {
  221. numPecas++;
  222. numBuracos--;
  223. switch( dir ) {
  224. case DIR_CIMA:
  225. pecas[y][x] = 0;
  226. pecas[y - 1][x] = 1;
  227. pecas[y - 2][x] = 1;
  228. return;
  229. case DIR_DIREITA:
  230. pecas[y][x] = 0;
  231. pecas[y][x + 1] = 1;
  232. pecas[y][x + 2] = 1;
  233. return;
  234. case DIR_BAIXO:
  235. pecas[y][x] = 0;
  236. pecas[y + 1][x] = 1;
  237. pecas[y + 2][x] = 1;
  238. return;
  239. case DIR_ESQUERDA:
  240. pecas[y][x] = 0;
  241. pecas[y][x - 1] = 1;
  242. pecas[y][x - 2] = 1;
  243. return;
  244. }
  245. }
  246. char encontraBuraco( ponto p, item resp, int* aux ) {
  247. int x = *aux % TAMANHO_Y_MATRIZ, y = *aux / TAMANHO_Y_MATRIZ;
  248. for( ; y < TAMANHO_Y_MATRIZ; y++ ) {
  249. for( ; x < TAMANHO_X_MATRIZ; x++ ) {
  250. if( pecas[y][x] == 0 ) {
  251. resp->p->x = x;
  252. resp->p->y = y;
  253. resp->dir = 0;
  254. return 1;
  255. }
  256. (*aux)++;
  257. }
  258. x = 0;
  259. }
  260. return 0;
  261. }
  262. void imprimeTabuleiro() {
  263. int x, y;
  264. for( y = 0; y < TAMANHO_Y_MATRIZ; y++ ) {
  265. for( x = 0; x < TAMANHO_X_MATRIZ; x++ ) {
  266. printf("%d ", pecas[y][x]);
  267. }
  268. printf("\n");
  269. }
  270. }
  271. int main(void) {
  272. scanf(" %hu %hu", &TAMANHO_X_MATRIZ, &TAMANHO_Y_MATRIZ );
  273. int x, y;
  274. char dir;
  275. pecas = (char**) malloc( TAMANHO_Y_MATRIZ * sizeof(char*) );
  276. if( !pecas ) masterError("Impossivel alocar memória para as linhas da matriz pecas.\n");
  277. for( y = 0; y < TAMANHO_Y_MATRIZ; y++ ) {
  278. pecas[y] = (char*) malloc( TAMANHO_X_MATRIZ * sizeof(char) );
  279. if( !pecas[y] ) masterError("Impossivel alocar memória para as colunas da linha Y matriz pecas.\n");
  280. for( x = 0; x < TAMANHO_X_MATRIZ; x++ ) {
  281. scanf(" %hd", (short int*) &pecas[y][x] );
  282. if( pecas[y][x] == 1 )
  283. numPecas++;
  284. else if( pecas[y][x] == 0 )
  285. numBuracos++;
  286. }
  287. }
  288. x = 0; y = 0; dir = 1;
  289. ponto curPonto = createPonto( 0, 0 );
  290. item it = createItem( 0, 0, 1 );
  291. int aux = 0;
  292. respPilha = criaPilha( PILHA_INIC_SIZE );
  293. VERBOSE = 0;
  294. while( numPecas > 1 ) {
  295. /*if( numIteracoes + 5 >= 10000 ) VERBOSE = 1; */
  296. if( VERBOSE ) printf("Loop: %d pecas\n", numPecas );
  297. aux = 0;
  298. while( GOKU_POWER_LEVEL > 9000 ) {
  299. if( VERBOSE ) printf("\tBusca > ");
  300. if( !encontraBuraco( curPonto, it, &aux ) ) {
  301. if( pilhaVazia( respPilha ) ) {
  302. printf("Tabuleiro sem solucao.\n");
  303. /* libera memória */
  304. exit(0);
  305. }
  306. /* não há mais buracos no tabuleiro. Backtrack */
  307. copiaValoresItem( it, topoPilha( respPilha ) );
  308. if( VERBOSE ) printf("Backtrack (%d,%d,%d)", it->p->x, it->p->y, (int) it->dir );
  309. desempilha( respPilha );
  310. adcionaAcaoErrada( respPilha, it->p, it->dir );
  311. desfazAcao( it->p->x, it->p->y, it->dir );
  312. aux = it->p->y * TAMANHO_Y_MATRIZ + it->p->x;
  313. } else if( VERBOSE ) {
  314. printf("(%d,%d)", it->p->x, it->p->y );
  315. }
  316. if( VERBOSE ) printf(" Dir: ");
  317. for( dir = 1; dir <= 4; dir++ ) {
  318. if( acaoValida( it->p, dir ) ) {
  319. if( !isAcaoErrada( respPilha, it->p, dir ) ) {
  320. break;
  321. } else {
  322. if( VERBOSE ) printf("[%d,BT] ", dir );
  323. }
  324. } else {
  325. if( VERBOSE ) printf("[%d,IN] ", dir );
  326. }
  327. }
  328. if( (int) dir <= 4 ) {
  329. if( VERBOSE ) printf("[%d,OK]\n", (int) dir );
  330. it->dir = dir;
  331. break;
  332. }
  333. if( VERBOSE ) printf("\n");
  334. aux++;
  335. }
  336. if( VERBOSE ) printf("\tEmpilhando (%d,%d,%d)... ", it->p->x, it->p->y, (int) it->dir);
  337. empilha( respPilha, it );
  338. if( VERBOSE ) printf("Sucesso!\n");
  339. if( VERBOSE ) printf("\tAtualizando Tabuleiro... ");
  340. realizaAcao( it->p->x, it->p->y, it->dir );
  341. if( VERBOSE ) printf("Sucesso!\n");
  342. copiaValoresPonto( curPonto, it->p );
  343. numIteracoes++;
  344. if( numIteracoes % 5000 == 0 && 0 ) {
  345. int i, j;
  346. imprimeTabuleiro();
  347. printf("[i]\t(x,y,dir): ERRORS\n");
  348. for( i = 0; i < respPilha->topo; i++ ) {
  349. printf("[%d]\t(%d,%d,%d)\t", i, respPilha->vetor[i]->p->x, respPilha->vetor[i]->p->y, (int) respPilha->vetor[i]->dir );
  350. for( j = 0; j < respPilha->permSize[i] && respPilha->permVect[i][j]->dir != 0 && j < 10; j++ )
  351. printf("(%d,%d,%d);", respPilha->permVect[i][j]->p->x, respPilha->permVect[i][j]->p->y, (int) respPilha->permVect[i][j]->dir );
  352. printf("\n");
  353. }
  354. /*exit(1); */
  355. }
  356. }
  357. while( !pilhaVazia( respPilha ) ) {
  358. it = topoPilha( respPilha );
  359. printf("(%d,%d,%d)\n", it->p->x, it->p->y, (int) it->dir );
  360. desempilha( respPilha );
  361. }
  362. imprimeTabuleiro();
  363. return 0;
  364. }