- #include <cstdlib>
- #include <iostream>
- #include <memory>
- #include <stdlib.h>
- using namespace std;
- /* THAÍS COSTELLA - EP 4 - O RATO E O QUEIJO
- O programa recebe como entrada dois números que correnspondem ao número
- de linhas e colunas do labirinto e sua configuração (-1 para obstaculo, 0
- para posição livre, -2 para o rato e -3 para o queijo. Ao final ele devolve
- a menor distância a ser percorrida pelo rato até o queijo*/
- struct Noh{
- Noh(int valor = -17, int linha = -17, int coluna = -17, Noh* anterior = NULL, Noh* proximo = NULL){
- distancia_ = valor;
- linha_ = linha;
- coluna_ = coluna;
- anter_ = anterior;
- prox_ = proximo;}
- int distancia_;
- int linha_;
- int coluna_;
- Noh* prox_;
- Noh* anter_;};
- struct Fila{
- Fila(Noh* comeco_ = NULL){comeco = comeco_;}
- Noh* comeco;};
- struct Entrada{
- int n_;
- int m_;
- int** tabuleiro_;};
- struct Posicao{
- int linhar;
- int colunar;
- int linhaq;
- int colunaq;};
- //______________________FUNÇÕES DA FILA IMPLEMENTADA COM LISTA DUPLAMENTE LIGADA
- // Função que constrói e retorna um apontador para o final da fila
- Noh* finalDaFila(Fila* fila){
- Noh* final = new Noh();
- if(fila->comeco->prox_ == NULL){
- final->anter_ = fila->comeco;
- fila->comeco->prox_ = final;
- return final;
- }
- else{
- Noh* percorre = fila->comeco->prox_;
- while(percorre->prox_ != NULL){
- percorre = percorre->prox_;
- }
- final->anter_ = percorre;
- percorre->prox_ = final;
- return final;
- }
- }
- void insere(Fila* fila, int valor, int linha, int coluna){
- Noh* novo = new Noh(valor, linha, coluna);
- if(fila->comeco->prox_ == NULL){
- novo->anter_ = fila->comeco;
- fila->comeco->prox_ = novo;
- return;
- }
- else{
- Noh* percorre = fila->comeco->prox_;
- while(percorre->prox_!= NULL){
- percorre = percorre->prox_;
- }
- percorre->prox_ = novo;
- novo->anter_ = percorre;
- }
- }
- void remove(Fila* fila){
- if(fila->comeco->prox_ == NULL){
- return;
- }
- else{
- if(fila->comeco->prox_->prox_ == NULL){ //ou seja, só há um
- Noh* deletado = fila->comeco->prox_;
- fila->comeco->prox_ = NULL;
- delete deletado;
- return;
- }
- Noh* deletado = fila->comeco->prox_;
- deletado->prox_->anter_ = fila->comeco;
- fila->comeco->prox_ = deletado->prox_;
- delete deletado;
- return;
- }
- }
- bool vazia(Fila* fila){
- Noh* final = finalDaFila(fila);
- if(final->anter_ == fila->comeco) return true;
- else return false;
- }
- //____________________________________________________________FUNÇÕES AUXILIARES
- // Função para ler e armazenar os dados de entrada
- Entrada entrada(){
- Entrada dados;
- scanf("%d", &dados.n_);
- scanf("%d", &dados.m_);
- int** tabuleiro = (int**) calloc (dados.n_, sizeof(int*));
- for (int i = 0; i < dados.n_; i++)
- tabuleiro[i] = (int*) calloc (dados.m_, sizeof(int));
- for(int i=0; i < dados.n_; i++){
- for(int j=0; j < dados.m_; j++){
- scanf("%d", &tabuleiro[i][j]);
- }
- }
- dados.tabuleiro_ = tabuleiro;
- return dados;
- }
- // Função que procura e armazena as posições do rato e do queijo
- Posicao posicaoRatoEqueijo(Entrada dados){
- Posicao posicao;
- for(int i=0; i < dados.n_; i++){
- for(int j=0; j < dados.m_; j++){
- if(dados.tabuleiro_[i][j] != -2 && dados.tabuleiro_[i][j] != -3)
- continue;
- else{
- if(dados.tabuleiro_[i][j] == -2){
- posicao.linhar = i;
- posicao.colunar = j; }
- if(dados.tabuleiro_[i][j] == -3){
- posicao.linhaq = i;
- posicao.colunaq = j;}
- }
- }
- }
- return posicao;
- }
- // Checa a validade de uma posição como vizinho(abaixo a explicação)
- bool vizinhoOK(Entrada dados, int linha_v, int coluna_v){
- if(linha_v >= 0 && linha_v < dados.n_ && coluna_v >= 0 && coluna_v < dados.m_){
- if(dados.tabuleiro_[linha_v][coluna_v] >= 0) return true;
- if(dados.tabuleiro_[linha_v][coluna_v] == -2) return true;
- }
- else return false;
- }
- //______________________________________________________________FUNÇÃO PRINCIPAL
- // Função que vai retornar a distância entre o rato e o queijo.
- // Calcula, a partir do queijo, as distâncias dos seus adjascentes (e adjascentes
- // de adjascentes) até o rato.
- int calculaDistancias(Entrada dados, Posicao ratoEqueijo, Fila* fila){
- int distancia = 0;
- int linha = ratoEqueijo.linhaq;
- int coluna = ratoEqueijo.colunaq;
- insere(fila, distancia, linha, coluna); // coloco o queijo na fila
- while(true){
- // coloco todos os adjascentes daquela posicao (se forem válidos)
- // na fila ( distancia + 1, linha_vizinho, coluna_vizinho)
- if(vizinhoOK(dados, linha+1, coluna)){
- insere(fila, distancia+1, linha+1, coluna);
- // se essa posicao for o rato, aumenta 1 a distancia e sai do looping
- if(dados.tabuleiro_[linha+1][coluna] == -2){
- distancia = distancia + 1;
- break;
- }
- // senão, muda o tabuleiro com -1 para indicar que já foi pra fila
- dados.tabuleiro_[linha+1][coluna] = -1;
- }
- if(vizinhoOK(dados, linha-1, coluna)){
- insere(fila, distancia+1, linha-1, coluna);
- if(dados.tabuleiro_[linha-1][coluna] == -2){
- distancia = distancia + 1;
- break;
- }
- dados.tabuleiro_[linha-1][coluna] = -1;
- }
- if(vizinhoOK(dados, linha, coluna+1)){
- insere(fila, distancia+1, linha, coluna+1);
- if(dados.tabuleiro_[linha][coluna+1] == -2){
- distancia = distancia + 1;
- break;
- }
- dados.tabuleiro_[linha][coluna+1] = -1;
- }
- if(vizinhoOK(dados, linha, coluna-1)){
- insere(fila, distancia+1, linha, coluna-1);
- if(dados.tabuleiro_[linha][coluna-1] == -2){
- distancia = distancia + 1;
- break;
- }
- dados.tabuleiro_[linha][coluna-1] = -1;
- }
- //tira o da primeira posicao
- if(!vazia(fila)){
- remove(fila);
- // vê quem está na ponta da fila
- linha = fila->comeco->prox_->linha_;
- coluna = fila->comeco->prox_->coluna_;
- distancia = fila->comeco->prox_->distancia_;
- }
- else{
- cout<<"não há solução";
- return 0;
- }
- }
- return distancia;
- }
- int main(int argc, char *argv[])
- {
- Fila* fila = new Fila();
- Noh* comeco = new Noh();
- fila->comeco = comeco;
- Entrada dados = entrada();
- Posicao ratoEqueijo = posicaoRatoEqueijo(dados);
- int x = calculaDistancias(dados, ratoEqueijo,fila);
- cout << "\n" << x;
- delete fila;
- delete comeco;
- system("PAUSE");
- return EXIT_SUCCESS;
- }