DFS

这篇博客介绍了深度优先搜索(DFS)的基本概念和算法过程,并提供了几个使用DFS解决的实际问题,包括李白打酒问题、六角填数问题以及地宫取宝问题的解决方案。通过递归和回溯的方式,展示DFS如何寻找问题的解。


搜索算法是利用计算机的高性能来有目的的穷举一个问题解空间的部分或所有的可能情况,从而求出问题的解的一种方法。

 --百度百科

搜索树的概念:

将搜索过程中每一步的状态变成树的一个节点,根节点为初始状态,搜索便是不断遍历这棵树,直到找到目标状态为止。

DFS主要算法过程:对于一个在有效的范围内的状态A,对于其所有的子状态,选择一种进行搜索,递归这一子状态,直到达到叶子节点,然后回溯到父亲节点,对另一种子状态进行搜索。

伪代码:

void DFS(状态A){

if(A不合法)

return;

if(A为目标状态)

输出

if(A不为目标状态)

DFS(A+i);//递归调用

}

实例   李白打酒

    话说大诗人李白,一生好饮。幸好他从不开车。 一天,他提着酒壶,从家里出来,酒壶中有酒2斗。他边走边唱:

    无事街上走,提壶去打酒。逢店加一倍,遇花喝一斗。

    这一路上,他一共遇到店5次,遇到花10次,已知最后一次遇到的是花,他正好把酒喝光了。

    请你计算李白遇到店和花的次序,可以把遇店记为a,遇花记为b。则:babaabbabbabbbb 就是合理的次序。像这样的答案一共有多少呢?请你计算出所有可能方案的个数(包含题目给出的)

代码如下:

int ans=0;
char s[15];
void dfs(int a,int b,int jiu,int sum){
    if(!jiu&&!a&&!b&&s[14]=='b'){//检索成功的条件。
            ans++;
            return;
            }
            if(a>0){//递归调用
                    s[sum]='a';
            dfs(a-1,b,jiu*2,sum+1);
            }
            if(b>0&&jiu>0){
                    s[sum]='b';
            dfs(a,b-1,jiu-1,sum+1);
            }
            }
int main(){
    int jiu=2;
    int a=5;
    int b=10;
    int sum=0;
    dfs(a,b,jiu,sum);
    printf("%d\n",ans);
    return 0;

}

运行结果:14

六角填数

    如图【1.png】所示六角形中,填入1~12的数字。使得每条直线上的数字之和都相同。图中,已经替你填好了3个数字,请你计算星号位置所代表的数字是多少?请通过浏览器提交答案,不要填写多余的内容。


代码如下:

#include<stdio.h>

int mun[9]={2,4,5,6,7,9,10,11,12};//只剩九个数未填

int vis[9];

int a[9];

int check(){

int t1,t2,t3,t4,t5,t6;

t1=1+a[2]+a[4]+a[8];

t2=1+a[1]+a[5]+a[9];

t3=a[5]+a[6]+a[7]+a[8];

t4=8+a[1]+a[2]+a[3];

t5=8+a[6]+a[9]+3;

t6=3+a[3]+a[4]+a[7];

if(t1==t2&&t2==t3&&t3==t4&&t4==t5&&t5==t6){

printf("%d\n",a[9]);

return 1;

}

return 0;

}

void dfs(int n){

int i;

if(n=10&&check()){//搜索成功的条件九个变量a[i]均拥有了互不相同的值,且满足六条边和相等的条件 

if(!vis[i]){//如果num[i]未被赋给a[i]

a[n]=num[i];//给a[n]赋值

vis[i]=1;//做标记

dfs(n+1);//查找下一个

vis[i]=0;//取消标记

}

}

}

int main(){

int n=0;

memset(vis,0,sizeof(vis));//标记数组清零

return 0;

}

void *memset(void *s, int ch, size_t n);

函数解释:将s中前n个字节 (typedef unsigned int size_t )用 ch 替换并返回 s 。

memset:作用是在一段内存块中填充某个给定的值,它是对较大的结构体数组进行清零操作的一种最快方法。

地宫取宝

X 国王有一个地宫宝库。是 n x m 个格子的矩阵。每个格子放一件宝贝。每个宝贝贴着价值标签。

地宫的入口在左上角,出口在右下角。

小明被带到地宫的入口,国王要求他只能向右或向下行走。

过某个格子时,如果那个格子中的宝贝价值比小明手中任意宝贝价值都大,小明就可以拿起它(当然,也可以不拿)。

当小明走到出口时,如果他手中的宝贝恰好是k件,则这些宝贝就可以送给小明。 

请你帮小明算一算,在给定的局面下,他有多少种不同的行动方案能获得这k件宝贝。

【数据格式】


    输入一行3个整数,用空格分开:n m k (1<=n,m<=50, 1<=k<=12)


    接下来有 n 行数据,每行有 m 个整数 Ci (0<=Ci<=12)代表这个格子上的宝物的价值


    要求输出一个整数,表示正好取k个宝贝的行动方案数。该数字可能很大,输出它对 1000000007 取模的结果。


例如,输入:
2 2 2
1 2
2 1
程序应该输出:
2


再例如,输入:
2 3 2
1 2 3
2 1 5
程序应该输出:
14

代码如下;

#include<stdio.h>

long long ans=0;

int a[55][55];

int n,m,k;

const int inf=0x3f3f3f3f;

void dfs(int x,int y,int pre,int max){

if(pre>k)

return;

if(pre==k||pre==k-1&&max<a[x]a[y]){//搜索成功的条件 走到终点时刚好拿到了K件礼物或者拿到了k-1件礼物,在该点的礼物的价值又大于之前拿到的最大价值。此时方案数加一

ans++;

return;

}

if(x<n-1){//向下走

if(max<a[x][y])

dfs(x+1,y,pre+1,a[x][y]);

dfs(x+1,y,pre,max);

}

if(y<m-1){//向右走

if(max<a[x][y])

dfs(x,y+1,pre+1,a[x][y]);

dfs(x,y+1,pre,max);

}

}

int main(){

while(~scanf("%d%d%d",&n,&m,&k){//当没有输入时退出循环

for(int i=0;i<n;i++)

for(int j=0;j<m;j++)

scanf("%d",a[x]a[y]);

ans=0;

x=0;

y=0;

pre=0;

max=-inf;

dfs(x,y,pre,max);

}

return 0;

}






评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值