Resolução de Problemas - Canibais e Missionários
De Aulas
Afluentes: Inteligência Artificial
Estrutura de Dados
Estrutura de Dados do problema dos Canibais e Missionários
LadoEsquerdo ( Canibais = inteiro Missionarios = inteiro Canoa = booleano )
Na forma de Vetor:
(C, M, J) (3, 3, T)
Observações:
- C = Canibais
- M = Missinários
- J = Jangada (não deu pra colocar C de Canoa)
- T (ou True), a canoa está do lado esquerdo, se do lado direito, então F (False)
- Para saber como está do lado direito, basta calcular:
- C2 = 3 - C
- M2 = 3 - M
- e J = F
Restrições
- Max2 - Máximo de passageiros na canoa é 2 pessoas
- !C>M - Nao pode ter mais canibais que missionários
- 1P - Mínimo de passageiros numa canoa é 1 pessoa
Regras / Métodos
- 1MD - Transportar 1 Missionário para a direita
- 2MD - Transportar 2 Missionários para a direita
- 1CD - Transportar 1 Canibal para a direita
- 2CD - Transportar 2 Canibais para a direita
- CMD - Transportar 1 Canibal e 1 Missionário para a direita
- 1ME - Transportar 1 Missionário para a esquerda
- 2ME - Transportar 2 Missionários para a esquerda
- 1CE - Transportar 1 Canibal para a esquerda
- 2CE - Transportar 2 Canibais para a esquerda
- CME - Transportar 1 Canibal e 1 Missionário para a esquerda
Teste de Mesa e Estados
0. (3, 3, 1, 0, 0, 0) - CMD 1. (2, 2, 0, 1, 1, 1) - 1ME 2. (2, 3, 1, 1, 0, 0) - 2CD 3. (0, 3, 0, 3, 0, 1) - 1CE 4. (1, 3, 1, 2, 0, 0) - 2MD 5. (1, 1, 0, 2, 2, 1) - CME 6. (2, 2, 1, 1, 1, 0) - 2MD 7. (2, 0, 0, 1, 3, 1) - 1CE 8. (3, 0, 1, 0, 3, 0) - 2CD 9. (1, 0, 0, 2, 3, 1) - 1CE 10.(2, 0, 1, 1, 3, 0) - 2CD 11.(0, 0, 0, 3, 3, 1)
Algoritmo
Principal
Inicio Enquanto Não TERMINOU Fazer Operação = LerDoTeclado Se VALIDA(Operacao) Entao Se Operacao == 1M-AB Então LadoA.Missionario-- LadoB.Missionario++ LadoA.Canoa = Falso LadoB.Canoa = Verdadeiro Senão ... // Demais operações Fim Se Fim Se Fim Enquanto Fim
TERMINOU
Inicio Se (LadoB.Canibais == 3) e (LadoB.Missionarios == 3) Então Retorna Verdadeiro Senão Retorna Falso Fim Se Fim
VALIDA
Inicio (operação) Se (operacao == 1M-AB) Então Se LadoA.Missionarios == 0 Então Retorna Falso Fim Se Se (LadoA.Missionarios - 1 < LadoA.Canibais) Então Retorna Falso Fim Se Senão ... // Demais Operações Fim Se Retorna Verdadeiro Fim
Programa
Programa em Python com base na Estrutura de Dados definida e algoritmos apresentados.
passo = 0
estado = (3, 3, True)
def mover(estado_atual, canibais, missionarios):
global passo
C, M, L = estado_atual
# Direção da travessia:
# -1 se for da esquerda para a direita,
# +1 se da direita para a esquerda
direcao = -1 if L else 1
# Atualiza canibais e missionários do lado esquerdo
C += direcao * canibais
M += direcao * missionarios
# Inverte lado da canoa
L = not L
passo += 1
imprimir_estado((C, M, L))
return C, M, L
def estado_valido(estado):
C, M, _ = estado
C2 = 3 - C
M2 = 3 - M
# Nenhum número pode ser negativo ou maior que 3
if not (0 <= C <= 3 and 0 <= M <= 3):
return False, False
if not (0 <= C2 <= 3 and 0 <= M2 <= 3):
return False, False
# Missionários nunca podem ser menos que canibais,
# nos dois lados (se tiver missionários)
if M > 0 and C > M:
return False, False
if M2 > 0 and C2 > M2:
return False, False
if C == 0 and M == 0:
return True, True
return True, False
def imprimir_estado(estado_atual):
global passo
C, M, L = estado_atual
lado = r"\___/ " if L else r" \___/"
print(f"{passo:2}. Esquerda: {C}C, {M}M", end=" ")
print(f"| {lado}", end=" ")
print(f"| Direita: {3 - C}C, {3 - M}M", end=" ")
valido, objetivo = estado_valido(estado_atual)
print("|", "valido" if valido else "invalido", end="")
print(", Objetivo Alcançado..." if objetivo else "")
imprimir_estado(estado)
estado = mover(estado, 1, 1)
estado = mover(estado, 0, 1)
estado = mover(estado, 2, 0)
estado = mover(estado, 1, 0)
estado = mover(estado, 0, 2)
estado = mover(estado, 1, 1)
estado = mover(estado, 0, 2)
estado = mover(estado, 1, 0)
estado = mover(estado, 2, 0)
estado = mover(estado, 1, 0)
estado = mover(estado, 2, 0)
Saída:
0. Esquerda: 3C, 3M | \___/ | Direita: 0C, 0M | valido
1. Esquerda: 2C, 2M | \___/ | Direita: 1C, 1M | valido
2. Esquerda: 2C, 3M | \___/ | Direita: 1C, 0M | valido
3. Esquerda: 0C, 3M | \___/ | Direita: 3C, 0M | valido
4. Esquerda: 1C, 3M | \___/ | Direita: 2C, 0M | valido
5. Esquerda: 1C, 1M | \___/ | Direita: 2C, 2M | valido
6. Esquerda: 2C, 2M | \___/ | Direita: 1C, 1M | valido
7. Esquerda: 2C, 0M | \___/ | Direita: 1C, 3M | valido
8. Esquerda: 3C, 0M | \___/ | Direita: 0C, 3M | valido
9. Esquerda: 1C, 0M | \___/ | Direita: 2C, 3M | valido
10. Esquerda: 2C, 0M | \___/ | Direita: 1C, 3M | valido
11. Esquerda: 0C, 0M | \___/ | Direita: 3C, 3M | valido, Objetivo Alcançado...