数据结构与算法 / 回溯算法(八皇后、0 - 1 背包)

本文介绍了回溯算法的基本概念,并通过两个经典案例——八皇后问题和0-1背包问题,展示了回溯算法的具体实现过程及应用效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

回溯算法,顾名思义,就是在没有得到最优解的前提下,不断的返回至前面的岔路口位置,重新选择,直至遍历了所有的情况或者得到的预期最优解的情况下再结束。

与贪心算法不同的是,回溯算法理论上是可以得到最优解,而贪心算法则尽可能在快的情况下得到较理想的结果。

一、八皇后

下面的栗子就是八皇后问题,是一个典型的回溯算法应用栗子。其实本质上就是遍历所有的可能性,最后满足条件者打印出来。 

#include <iostream>

unsigned int g_count = 0;

bool isOK(unsigned char *p_result, const unsigned char &row, const unsigned char &column);
void PrintResult(unsigned char *p_result);
void Calc8Queens(unsigned char *p_result, const unsigned char &row);

int main()
{
    unsigned char result[8] = {5, 5, 5, 5, 5, 5, 5, 5};
    Calc8Queens(result, 0);
    std::cout << "共有 " << g_count << " 个结果" << std::endl;
    return 0;
}

bool isOK(unsigned char *p_result, const unsigned char &row, const unsigned char &column)
{
    if (p_result == nullptr)
        return false;
    unsigned char leftup = column - 1;
    unsigned char rightup = column + 1;
    for (int i = row - 1; i >= 0; --i)
    {
        if (p_result[i] == column)
            return false;
        if (leftup >= 0)
        {
            if (p_result[i] == leftup)
                return false;
        }
        if (rightup < 8)
        {
            if (p_result[i] == rightup)
                return false;
        }
        leftup--;
        rightup++;
    }
    return true;
}

void PrintResult(unsigned char *p_result)
{
    if (p_result == nullptr)
        return;
    for (unsigned char i = 0; i < 8; ++i)
    {
        for (unsigned char k = 0; k < p_result[i]; ++k)
            std::cout << "-"
                      << " ";
        std::cout << "a"
                  << " ";
        for (unsigned char k = p_result[i] + 1; k < 8; ++k)
            std::cout << "-"
                      << " ";
        std::cout << std::endl;
    }
    std::cout << std::endl;
    std::cout << std::endl;
    return;
}

void Calc8Queens(unsigned char *p_result, const unsigned char &row)
{
    if (p_result == nullptr)
        return;
    if (row >= 8)
    {
        g_count++;
        PrintResult(p_result);
        return;
    }
    for (int column = 0; column < 8; ++column)
    {
        if (isOK(p_result, row, column))
        {
            p_result[row] = column;
            Calc8Queens(p_result, row + 1);
        }
    }
    return;
}

结果太多了,就不写出来了,共有 92 个可能性。 

二、0 - 1 背包

#include <iostream>

unsigned int g_max = 0;
void func(const int &index, const int &cw, const int *const pitems, const int &count, const int &maxW);

int main()
{
    int items[10] = {80, 20, 90, 9, 50, 6, 70, 8, 9, 10};
    func(0, 0, items, 10, 111);
    std::cout << "所能容纳的最大的物件重量为 " << g_max << std::endl;
    return 0;
}

void func(const int &index, const int &cw, const int *const pitems, const int &count, const int &maxW)
{
    if (cw == maxW || index >= count)
    {
        if (cw > g_max)
            g_max = cw;
        return;
    }
    func(index + 1, cw, pitems, count, maxW);
    if (cw + pitems[index] <= maxW)
        func(index + 1, cw + pitems[index], pitems, count, maxW);
    return;
}

结果为 110 。

 

(SAW:Game Over!)

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值