2020-09-06 深度优先搜索学习

   日期:2020-09-08     浏览:85    评论:0    
核心提示:深度优先搜索练习关于凑数 (参考书目《啊哈!算法》)从1-9共9张扑克牌中放到9个盒子里,并使得____+____=____成立(每个下划线上填一个三位数)#includeint a[10],book[10],total;//这里还有需要注意的地方C语言全局变量默认为0void dfs(int step){ int i; if(step==10)//设立终止点 { if(a[1]*100+a[2]*10+a[3]+a[4]*100+a[5]*10+

深度优先搜索练习

关于凑数 (参考书目《啊哈!算法》)

从1-9共9张扑克牌中放到9个盒子里,并使得____+____=____成立(每个下划线上填一个三位数)

#include<stdio.h>
int a[10],book[10],total;
//这里还有需要注意的地方C语言全局变量默认为0

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]){
			total++;
			printf("%d%d%d+%d%d%d=%d%d%d\n",a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9]);
		} 	
	return ;   
}		
	 for(int i=1;i<=9;i++){
		if(book[i]==0){  //说明i号扑克牌还在手里,需要放入step号盒子
			a[step]=i;//将i号扑克牌放到第step个盒子中
			book[i]=1;//此时i号扑克牌已经被使用 
			dfs(step+1);
			
			//并且step在下一步中每次调用都会自动加1 
			book[i]=0;
			
		}
	}
	return;//这里表示这一级别的dfs函数已经结束了,返回上一级 dfs函数 

}
int main(){
	dfs(1);   //dfs函数的开始 
	printf("%d",total/2);
	//之所以除以2是因为会出现173+286=459和286+173=459是同一种解的情况
	return 0;
}

为了更方便的理解,我们可以尝试先自己先演示一次。例如:123+456=789,显然是不成立的。程序会直接return,退回上一级,即123+345=78_,而此时循环已经结束,所以又会退回更上一级,123+456=7__。本轮中 i 此时等于8,循环进入下一级,i=9, 此时123+456=79_。执行dfs(9),得到123+456=798。不成立,按照上述步骤继续重复往更上一级后退 。

有了上面的经验,我们继续进行下一道题

求部分和

给定质整数a1,a2,…an,判断是否可以从中选出若干数,使他们的和恰好为k.
样例输入:
n=4, k=13 a={1,2,4,7}
输出
YES
2,4,7
输入
n=4, k=15 a={1,2,4,7}
输出
NO

#include<stdio.h>
#include<string.h>
int a[30],book[30];// book[i]用来判断a[i]是否使用了 
int n,s,sum,judge,judgeT;//全局变量默认为0 
void dfs(int step)
{
    int i;
     if(s==sum)
        {
            judge=1;
                printf("YES\n");
                for(i=0; i<n; i++)
                    if(book[i])
                        printf("%d ",a[i]);
                printf("\n");
                return;
        } 
    if(s>sum){
    	judgeT=1;
		//减少运算量 
	}
    int  num;
    if(judgeT==0){ 
    	for(num=step; num<n; num++)
    	{
        	s=s+a[num];
       		book[num]=1;
			dfs(num+1);//这个与上一题不一样的地方在于可能会出现num+1之后大于n的情况,但是不影响程序运行 
        	s= s-a[num];//当程序运算到这一步说明并未出现s==sum的情况,s的值需要退回上一级。 
        	book[num]=0;
        	judgeT=0;
    	}
    } 
}
int main(void)
{
    int i;
    while(~scanf("%d%d",&n,&sum))//~scanf等效于scanf()!=EOF。没有输入的时候自动退出。 
    {
        judge=0;
        memset(book,0,sizeof(book));
         //将所有book[]都设置为0 ,这段代码纯画蛇添足(我只是用来复习一下memset)
        for(i=0; i<n; i++)
            scanf("%d",&a[i]);
        dfs(0);
        if(judge==0) printf("NO\n");
    }
    return 0;
}

这道题的关键是在于不是所有输入的数字都会被最终使用,所以这道题的判断终止标准与上一道题截然不同。我觉得只需要在每次调用dfs时使用return语句即可(目前我没有看出来有什么不妥当的地方)。本题中我认为最关键的一步思考是在于s= s-a[num]; 同时judgeT用来减少计算量也是很重要的一步。
`

总结:

深度优先搜索重点在于思考“当前情况下如何去做”,至于“下一步如何去做”则与“当前情况下如何去做”有着共同之处
深度优先搜索基本模型

void dfs(int step){
	判断边界(可以灵活调整判断边界代码的位置但是必须要有)
	通用型尝试每一种可能 for(i=0;i<n;i++){
		继续下一步 dfs(step+1)
	}
	return;
}
 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服