Day22:算法篇之动态回溯

一、动态回溯相关

1.动态回溯:

(寻路算法    深度寻路算法)

2.动态回溯算法思想:

        ① 针对问题来解空间:  根据实际需求用不同方式来描述
            深度寻路算法: 要找到起点到终点的路径   二维数组来描述地图
        ② 确定易于搜索的解空间结构,并构造相应的判断函数
        ③ 用深度优先搜索的方式来解决问题,并要有合适的回溯方式(栈)

    动态回溯 == 问题的解空间 + 深度优先搜索 + 判断结果的结构 + 回溯

3.动态回溯一般用来解决哪些问题:

   ① 寻路  ②货物装载  ③0-1背包问题      ④图的着色问题(涂格子)
   ⑤电路排版问题    ⑥ 旅行者售后员问题   ⑦N皇后问题

二、典例----N皇后问题分析

1.问题规则+算法流程分析       

 8皇后问题: 国际象棋棋盘   在任意两个皇后不能互相触及的前提下 有多少种摆法
    
    1 问题的解空间 : 二维数组
    2 深度优先搜索 : 递归 一个个去摆  摆了N个皇后结束
    3 判断结果     : 判断能不能摆  数量是否达标
    4 回溯        :  给二维数组元素赋值 为1 表示摆放好了 赋值为0 就是回退  

2.代码实现

// N皇后问题.cpp : 定义控制台应用程序的入口点。
//
#include<cstdio>
#define TEST 1

#define N  4
//用来记录有多少种解法
int cnt = 0;

//遍历整个棋盘
void travel(int Q[N][N]);

//N皇后问题
void Queen(int j, int Q[N][N]);

//判断 i j 位置是否能放皇后 如果能 返回true 否则 返回false
bool isOkPos(int i, int j, int Q[N][N]);

int main()
{
	int Q[N][N] = { 0 };//0表示没有放皇后  1表示放了皇后
	Queen(0, Q);
	printf("解法种数为:%d\n", cnt);
	return 0;
}

//N皇后问题
void Queen(int j, int Q[N][N])
{
	if (N == j)
	{//N个皇后都已经放置好了
#if TEST
		travel(Q);//遍历整个地图
#endif
		cnt++;
		return;
	}
	for (int i = 0; i < N; i++)
	{//y坐标 
		if (isOkPos(i, j, Q))
		{//能放
			Q[i][j] = 1;//放
			Queen(j + 1, Q);//放下一个
			Q[i][j] = 0;//回溯
		}
	}
}

//遍历整个棋盘
void travel(int Q[N][N])
{
	printf("-------------------------------------------\n");
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N; j++)
		{
			printf("%d ", Q[i][j]);
		}
		printf("\n");
	}
	printf("-------------------------------------------\n");
}

//判断 i j 位置是否能放皇后 如果能 返回true 否则 返回false
bool isOkPos(int i, int j, int Q[N][N])
{
	int s;//s i 垂直 y轴
	int t;//t j 水平 x轴

	//横向判断
	for (s = i, t = 0; t < N; t++)
	{
		if (Q[s][t] == 1 && j != t) return false;
	}
	//纵向判断
	for (t = j, s = 0; s < N; s++)
	{
		if (Q[s][t] == 1 && s != i) return false;
	}

	//左上
	for (t = j - 1, s = i - 1; s >= 0 && t >= 0; s--, t--)
	{
		if (Q[s][t] == 1) return false;
	}

	//左下
	for (t = j - 1, s = i + 1; s < N && t >= 0; s++, t--)
	{
		if (Q[s][t] == 1) return false;
	}

	//右上
	for (t = j + 1, s = i - 1; s >=0 && t < N; s--, t++)
	{
		if (Q[s][t] == 1) return false;
	}
	//右下
	for (t = j + 1, s = i + 1; s < N && t < N; s++, t++)
	{
		if (Q[s][t] == 1) return false;
	}
	return true;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_Ocean__

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值