Notas sobre Algoritmo DFS

O algoritmo DFS (Busca em Profundidade) é frequentemente utilizado em competições como a Blue Cup, especialmente para problemas de alocação e navegação em grafos/trees. Aqui, discutiremos dois tipos principais de problemas que envolvem DFS.

Tipo Um: DFS para Processos de Alocação

Exemplo 1: Pouso de Aviões

Descrição do Problema:

N aviões estão prontos para pousar em um aeroporto com uma única pista de pouso. Cada avião i chega ao aeroporto no momento Ti e pode esperar até Di momentos antes de precisar pousar, levando Li momentos para completar o procedimento de pouso. Os aviões podem pousar imediatamente após o anterior, mas não podem iniciar o procedimento enquanto outro está em andamento. Determinar se todos os aviões podem pousar com segurança.

Formato de Entrada:

A entrada contém múltiplos conjuntos de dados. A primeira linha contém um inteiro T, indicando o número de conjnutos de teste. Para cada conjunto de dados, a prmieira linha contém um inteiro N. As próximas N linhas contêm três inteiros: Ti, Di e Li.

Formato de Saída:

Para cada conjunto de dados, imprimir "SIM" ou "NAO", indicando se todos os aviões podem pousar com segurança.

Código Exemplo:

def explorar(avioes, pousaram, total_avioes, tempo_atual, avioes_pousados):
    if avioes_pousados == total_avioes:
        return True
    for i in range(total_avioes):
        if pousaram[i]:
            continue
        if avioes[i][1] < tempo_atual:
            return False
        pousaram[i] = True
        if explorar(avioes, pousaram, total_avioes, max(tempo_atual, avioes[i][0]) + avioes[i][2], avioes_pousados + 1):
            return True
        pousaram[i] = False
    return False

casos_teste = int(input())
for _ in range(casos_teste):
    n = int(input())
    avioes = []
    for _ in range(n):
        a, b, c = map(int, input().split())
        avioes.append((a, a + b, c))
    pousaram = [False] * n
    if explorar(avioes, pousaram, n, 0, 0):
        print("SIM")
    else:
        print("NAO")

Exemplo 2: Distribuição de Doces

Descrição do Problema:

Há dois tipos de doces, com 9 e 16 unidades respectivamente, a serem distribuídos entre 7 crianças, onde cada criança deve receber entre 2 e 5 doces no total. Calcular quantas maneiras diferentes existem de distribuir todos os doces.

Solução:

A chave é evitar contar soluções repetidas. Utilizamos recursão para distribuir os doces entre as crianças.

Código Exemplo:

def distribuir_doces(indice, doce1, doce2):
    global contagem
    if indice >= 8:
        if doce1 == 0 and doce2 == 0:
            contagem += 1
        return
    for i in range(doce1 + 1):
        for j in range(doce2 + 1):
            if 2 <= i + j <= 5:
                distribuir_doces(indice + 1, doce1 - i, doce2 - j)

contagem = 0
distribuir_doces(1, 9, 16)
print(contagem)

Tipo Dois: DFS em Árvores

Exemplo 1: Guia Turístico

Descrição do Problema:

Um parque turístico possui N pontos de interesse conectados por N-1 estradas formando uma árvore. Um guia deve levar turistas por K dessses pontos em uma ordem específica, mas pode omitir um ponto. Calcular o tempo total necessário para visitar K-1 pontos para cada ponto omitido.

Entrada:

A primeira linha contém N e K. As próximas N-1 linhas descrevem as estradas e seus tempos de percurso. A última linha lista os K pontos de interesse na ordem de visita.

Saída:

K tempos totais, um para cada ponto omitido.

Código Exemplo:

def caminhar(inicio, fim, atual, anterior, custo_total):
    global arestas
    global pesos
    if atual == fim:
        return custo_total
    for i, (destino, peso) in enumerate(arestas[atual]):
        if destino == anterior:
            continue
        temp = caminhar(inicio, fim, destino, atual, custo_total + pesos[inicio][fim][i])
        if temp > 0:
            return temp
    return 0

n, k = map(int, input().split())
arestas = [[] for _ in range(n + 1)]
pesos = [[{} for _ in range(n + 1)] for _ in range(n + 1)]
for _ in range(n - 1):
    u, v, t = map(int, input().split())
    arestas[u].append((v, t))
    arestas[v].append((u, t))
    pesos[u][v][v] = t
    pesos[v][u][u] = t
itinerario = list(map(int, input().split()))
total_custo = 0
custos_parciais = [0] * (k - 1)
for i in range(1, k):
    custos_parciais[i - 1] = caminhar(itinerario[i - 1], itinerario[i], itinerario[i - 1], -1, 0)
    total_custo += custos_parciais[i - 1]
print(total_custo - custos_parciais[0], end=' ')
for i in range(1, k - 1):
    print(total_custo - custos_parciais[i - 1] - custos_parciais[i] + caminhar(itinerario[i - 1], itinerario[i + 1], itinerario[i - 1], -1, 0), end=' ')
print(total_custo - custos_parciais[k - 2], end=' ')

Tags: dfs Algoritmos competicoes BlueCup Grafos

Publicado em 9-20 15:12