输出每行坐标的的c语言算法,数据结构_dfs深度优先算法入门(C语言)

数据结构_dfs深度优先算法入门(C语言)

文章目录

数据结构_dfs深度优先算法入门(C语言)

0.闲话

1.个人理解

2.全排列问题(1到n的排列组合)

2.八皇后问题求解

3.二维迷宫

(1)只输走出迷宫解的个数

(2)输出解的个数和路径

0.闲话

​ 才学习数据结构的dfs,做一下笔记记录一下,加深理解-.-

​ 我这里就简单讲一下我的理解和一下例子

​ 推荐学习资源(B站视频,原理和实例):

洛谷 普及组( CSP - J )试炼场 - 深度优先搜索 (DFS)

​ 编译环境:vc++6.0

1.个人理解

dfs,名叫深度优先搜索,就是从一个节点一直往深处搜索,直到走到尽头,再往回走,走下一个节点,再次深搜……就相当于来回遍历,一个人走迷宫。

所以,dfs是运用递归的方法,基于回溯的思想。而回溯就是基于栈结构。

栈结构的话,直接用数组来实现就可以了。

重点:C代码一定要从main函数开始看。

2.全排列问题(1到n的排列组合)

​ 全排列问题的一个重点:比如走迷宫一样,最开始有个起始点,下一步有多个选择。当我们要深搜时,如果没有一个固定的起始点,我们要假想构造一个0起始点,从0起始点开始往下走选择。以此来构造一个有规律可递归的函数。

17e68facf18225ae03770d5e1d9410d9.png

#include#define N 20

int n;//将其设置为全局变量

int visit[N]={0};//0代表未访问,1代表已访问。

int a[N] = {0};//记录全排列的方式。

//输出函数

void printF()

{

int i ;

for(i=1 ; i<=n ; i++)

printf("%5d",a[i]);

printf("\n");

}

void dfs(int x)//x代表递归的层数

{

int i;

if(x>n)

printF();//输出一种结果

for(i=1 ; i<=n ; i++)//递归时,每层都有循环

{

if(!visit[i])//i这个数是否排过序。

{

visit[i] = 1;//代表排过序

a[x] = i;//记录i

dfs(x+1);//进入下一层递归

//回溯,归零。

visit[i] = 0;

a[x] = 0;//这一步可以不写

}

}

}

int main()

{

printf("Please input n:");

scanf("%d",&n);

dfs(1);

return 0;

}

2.八皇后问题求解

简述规则就是,每行每列每个斜对角线只能站一个皇后,斜对角线包括左上到右下,和左下到右上,两种。

16c18261293b1ab0c64de7fb17c96753.png

31a79671c81c3d25ab7f8cea99d0124a.png

其实也是在全排列的基础上,加上八皇后特有的条件,进行递归。

#include#define N 20

int n;

int u[2*N] = {0};//右上到左下,防止皇后在同一斜对角线。

int v[2*N] = {0};//左上到右下,1代表斜对角线有皇后,0代表没有。

int list[N] = {0};//记录同一列

int a[N] = {0};//记录皇后的位置

int sum = 0;//记录解法

void printF()//将得到的结果输出

{

int i;

for( i=1 ; i<=n ; i++)

printf("%2d",a[i]);

putchar('\n');

}

void dfs(int x)

{

int i,j;

if( x>n )

{

sum++;

printF();//将一种结果输出

return ;

}

for(i=1 ; i<=n ; i++)//代表每行

{

if(list[i]==0 && u[x+i]==0 && v[x-i+n]==0)

{

//置一,代表这些位置不能再放皇后

list[i] = 1;

u[x+i] = 1;

v[x-i+n] = 1;//防止相减后是负数,同一所有加个n。

a[x] = i;//记录这个位置,x代表行,i代表列。

dfs(x+1);

//回溯,相当于栈结构

list[i] = 0;

u[x+i] = 0;

v[x-i+N] = 0;

a[x] = 0;

}

}

}

int main()

{

printf("Please input n: ");//n皇后

scanf("%d",&n);

dfs(1);

printf("There are %d sulutions!\n",sum);

}

3.二维迷宫

​ 输入:

35e187bddab28d15e08f1628e15eb611.png

​ 输入规则:

第一行输入行n、列m、障碍个数t

第二行分别输入起始坐标sx、sy和终点坐标fx、fy

第三行即后面依次每行输入一个障碍坐标,(根据输入的障碍个数)。

aa2022d668f27808c0e1c255417eee98.png

(1)只输走出迷宫解的个数

//三、二维迷宫求解:求解的个数。

#include#define N 20

int n,m,t;//行、列、障碍个数

int sx,sy,fx,fy;//起始位置,终点位置。

int map[N][N] = {0};//标记障碍。

int visit[N][N] = {0};//标记是否走过。

int xx[] = {1,0,-1,0};

int yy[] = {0,1,0,-1};

int sum = 0; //记录总数。

void dfs(int x,int y)

{

int i;

int dx,dy;//记录下一步的位置。

if(x==fx && y==fy)

sum++;

for(i=0 ; i<4 ; i++)

{

dx = xx[i] + x;

dy = yy[i] + y;

if(dx>=1 && dx<=n && dy>=1 && dy<=m && !map[dx][dy] && !visit[dx][dy])

{

visit[dx][dy] = 1;

dfs(dx,dy);

visit[dx][dy] = 0;

}

}

}

int main()

{

int x,y;//记录障碍位置。

printf("Please input : \n");

scanf("%d%d%d",&n,&m,&t);//输入行、列、障碍个数

scanf("%d%d%d%d",&sx,&sy,&fx,&fy);//数去起始坐标和终点坐标

while(t--)

{

scanf("%d%d",&x,&y);

map[x][y] = 1;//标记障碍坐标

}

visit[sx][sy] = 1;

dfs(sx,sy);//从起点位置开始递归。

printf("There are %d solution!\n",sum);

return 0;

}

(2)输出解的个数和路径

a5e373a74ffae478c84715970fe16fc4.png

#include#define N 20

int n,m,t;//n为行,m为列,t为障碍数。

int sx,sy;//起点坐标。

int fx,fy;//终点坐标。

int map[N][N] = {0};//地图,标记障碍。

int visit[N][N] = {0};//记录是否走过。

char a[N*N] = {0};//记录上下左右。

int sum = 0;//记录路径总数。

//输出函数,每次输出路径和增加解的个数

void printF(int k)

{

int i;

for(i=1 ; i<=k ; i++)

printf("%c",a[i]);

printf("\n");

sum++;

}

//x、y代表此时的位置,k代表走到第几步,方便记录路径。

void dfs(int x, int y, int k)

{

int i;

int dx,dy;//记录当前位置。

if(x==fx && y==fy)//走出迷宫输出输出路径

{

printF( k-1 );

return;

}

for(i=0 ; i<4 ; i++)//只有四种走法,上下左右。

{

//如果不满足则for循环回到这一层函数开始的坐标位置

dx = x;//这也是回溯,

dy = y;//这也是回溯

switch (i)

{

case 0:

dx++;

a[k] = 's';//上

break;

case 1:

dy++;

a[k] = 'y';//右

break;

case 2:

dx--;

a[k] = 'x';//下

break;

case 3:

dy--;

a[k] = 'z';//左

break;

}

if(dx>=1 && dx<=n && dy>=1 && dy<=m && !visit[dx][dy] && !map[dx][dy])//所有条件

{

visit[dx][dy] = 1;//标记走过

dfs(dx,dy,k+1);//进入下一层递归

visit[dx][dy] = 0;//回溯

}

}

}

//所有的x都代表行数,y代表列数。

int main()

{

int i;

int x,y;//记录障碍点。

printf("Please input : \n");

scanf("%d%d%d",&n,&m,&t);//输入行、列、障碍个数

scanf("%d%d%d%d",&sx,&sy,&fx,&fy);//数去起始坐标和终点坐标

while(t--)//循环输入障碍坐标

{

scanf("%d%d",&x,&y);

map[x][y] = 1;//标记障碍坐标

}

visit[sx][sy] = 1;//代表第一步已走。

dfs(sx,sy,1);//从起点位置开始递归。1代表第一步

printf("There are %d solutions!\n",sum);

return 0;

}

欢迎大家留言交流0.0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值