深度优先搜索 全排列与地图最短路径问题

以下代码描述的是向盒子a[step]放入数字,数字一共有n个,过程为向第一个盒子放入第一个数,第二个盒子放入第二个数,并将放入的数字利用book[i]进行标记,标记后就代表数字已经放入,依此放完后,当进入第n+1的盒子时表明所有的数字已经放入盒子中,然后打印出这一种排列。
一种排列拍完后返回前一个盒子(即第n个盒子),将这一个盒子的数字拿出,由于此时的数字循环已经到达最后一项,会直接返回到n-1的盒子,此时会将这个盒子里的数也拿出来,接下来会从n-1这一步继续循环到下一步,此时会发现第n个数已经取出,则会将第n个数放入第n-1的盒子,进入下一个盒子step=n时,会发现只有第n-1的数在手中,故将这个放入其中,最后进入step=n+1,打印出下一个排列。
通过上边的一些步骤可以求出全排列。
代码后边会有从1到3的全排列代码顺序

#include<stdio.h>
int a[10], book[10], n;
void dfs(int step)
{
    int i;
    if(step==n+1)
    {
        for ( i = 1; i <= n;i++)
            printf("%d", a[i]);
        printf("\n");
        return;
    }
    for ( i = 1; i <= n;i++)
    {
        if(book[i]==0)
        {
            a[step] = i;
            book[i] = 1;
            dfs(step + 1);
            book[i] = 0;
        }
    }
    return;
}
int main()
{
    scanf("%d", &n);
    dfs(1);
    return 0;
}

这是一个基于深度优先搜索的数的全排列
以123的全排列为例,我们会给出步骤便于理解

首先一二三依此放入每一个盒子中,进入第4的盒子,形成第一个全排列123
返回第3个盒子,取出盒子中的3
返回第2个盒子,取出盒子中的2
将3放入第二个盒子
继续将2放入第三个盒子
进入第四个盒子形成全排列132
将第三个盒子的2收回
第二个盒子的3收回
第一个盒子的1收回
放入2进入第一个盒子
放入1进入第二个盒子
放入3进入第三个盒子
进入第四个盒子形成全排列213
第三个盒子的3收回
第二个盒子的1收回
放入3进入第二个盒子
放入1进入第三个盒子
进入第四个盒子形成全排列231

经过如此步骤便可以得出123的全排列

只要是有一定顺序的全排列问题都可以利用此方法

以下是利用这种性质进行的一种计算
题目是利用1到9的排列出三位数加三位数等于另一个三位数的形式
并对数目进行记录

#include<stdio.h>
int cout;
int book[10];
int a[10];
void dfs(int step){
    int i;
    if(step==10)
    {
        if(a[1]*100+a[2]*10+a[3]+a[4]*100+a[5]*10+a[6]==a[7]*100+a[8]*10+a[9])
        {
            cout++;
            for (i = 1; i < 10;i++)
                printf("%d ", a[i]);
            printf("\n");
            
        }
        return;
    }
    for (i = 1; i <= 9;i++)
    {
        if(book[i]==0)
        {
        a[step] = i;
        book[i] = 1;
        dfs(step + 1);
        book[i] = 0;
        }
    }
    return;
}
int main()
{
    dfs(1);
    printf("%d", cout/2);
    return 0;
}

通过上边两个例子可以看出要这个算法可以算出任意一些数的全排列,
这其实就是一个无向图以任意顶点可以到达其余另外一些的点的路径,以一个为顶点,到下一个点后再以这个点为顶点到下一个没有到达的点

首先输入地图的长度和宽度,输入地图,0为可走,非0为不可走
输入起点和终点计算两点之间的路径最短

#include<iostream>
using namespace std;
int n;
int m;
int minstep = 999;
int zongx, zongy;
int a[51][51], book[51][51];
int nextx[4] = {0, 1, -1, 0};
int nexty[4] = {1, 0, 0, -1};
void dfs(int x, int y,int step){
    if(x==zongx&&y==zongy){
        if(step<minstep){
            minstep = step;
        }
        return;
    }
    int nx, ny;
    for (int i = 0; i < 4;i++){
        nx = x + nextx[i];
        ny = y + nexty[i];
        if(nx>=1&&nx<=n&&ny>=1&&ny<=m&&a[nx][ny]==0&&book[nx][ny]==0){
            book[nx][ny] = 1;
            dfs(nx, ny, step + 1);
            book[nx][ny] = 0;
        }
    }
    return;
}

    int main()
{
    
    cin >> n >> m;
    for (int i = 1; i <= n;i++){
        for (int j = 1; j <= m;j++){
            cin >> a[i][j];
        }
    }
    int startx, starty, step = 0;
    cin >> startx >> starty >> zongx >> zongy;
    book[startx][starty] = 1;
    dfs(startx, starty, step);
    cout << minstep;
}

地图有四个方向,首先我们要想到去四个方向时,x和y会有不同的四种不同的组合,分别为 {0,1}{0,-1}{1,0}{-1,0},定义两个数组,对应下标相同时,就是我们走向下一步的一种情况。我们定义的book数组是记录是否走过,走过记录为1,为走过默认0。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值