• 深搜+迭代


    **前言:**当普通dfs搜索答案时,有时会有搜索的深度较深状态较多,而答案所在的深度却比较小的情况,这样会有大量搜索浪费在无用但是又递归层数很大的情况上。对此可以在dfs的时候限定一个深度的状态,这个深度是从小到大枚举的,直到搜到答案。

    一、poj3141

    题目大意是给定一个正整数n,求经过多少次乘法或除法运算可以从x得到xn,可以使用中间得到的结果。

    思路:
    起始只有x的一次方,所以通过乘除得到的值应该用数组存起来后续可以循环遍历。开始只设定递归一次,判断是否达到目的,没有则多给一次递归机会,即deep+1。因为幂函数运算乘就可以做加法,除可以做减法,所以对于之前存入数组的每个值遍历时都dfs两种情况。
    还有一个很重要的剪枝,if(n<<(deep-m)<ans)//deep-m为剩余可走的步数,如果连n的deep-m次方都比ans小,则不可能。没有这个剪枝,十位数的数据都出不来。

    #include <bits/stdc++.h>
    using namespace std;
    int vis[10000],a[10000];
    int deep=0,ans;
    bool dfs(int m,int n)
    {
    	//cout<<m<<" "<<n<<" "<<deep<<" "<<ans<<endl;
    	if(n<<(deep-m)<ans)//deep-m为剩余可走的步数,如果连n的deep-m
    	次方都比ans小,则不可能
    		return false;
    	if(m==deep&&n==ans)//到了深度就判断是否为目标值
    		return true;
    	if(m>=deep)//超过深度直接返回假
    		return false;
    	a[m]=n;//将当前值记入数组中,因为后续每一步都可以用前面算得的值
    	for(int i=0;i<=m;i++)//遍历数组
    	{
    		int x=n+a[i];//乘法
    	//	if(vis[a[i]])
    		if(dfs(m+1,x))
    			return true;
    		x=n-a[i];//除法
    //		if(vis[a[i]])
    		if(dfs(m+1,x))
    			return true;
    	}
    	return false;//没返回成功,就返回假嘛,因为一定要
    	返回值的,不然while里面没办法判断
    }
    int main()
    {
    	while(cin>>ans)
    	{
    		deep=0;//一开始深度设置为0
    		if(ans==0)
    			break;
    		memset(vis,0,sizeof(vis));
    		memset(a,0,sizeof(a));
    		while(1)//只要没找到答案深度加一,继续找。
    		{
    			if(dfs(0,1))
    				break;
    			deep++;
    		}
    		cout<<deep<<endl;
    	}
    }
    

    二、DNA sequence

    题目大意:就是给出N个DNA序列,要求出一个包含这n个序列的最短序列是多长。
    **题目思路:**这道题还是有点难啊,感谢大神Sly_461的解析,原文链接为
    https://blog.csdn.net/acmer_sly/article/details/52673575(下面的代码就是他的)
    但还是有几点需要注意
    一、用二位字符数组储存多个DNA
    二、用pos数组储存每个DNA搜索到哪个位置了
    三、设置搜索深度,但起始深度为最长的那个DNA,因为最后的序列肯定得包含它嘛!
    四、当pos数组中全为各个DNA长度时,完成搜索,退出搜索
    五、每次dfs都是从四个字母中选一个,判断选的字母是否对Pos数组有贡献,有则使flag为1,继续下一次dfs。没贡献则没意思,不用继续dfs。
    六、在函数中另外定义一个pos数组记录各个DNA的新进度,用pos传入参数,避免了回溯的复杂过程。

    #include<stdio.h>
    #include<string.h>
    int n;     
    int ans;        //最后答案 
    char str[10][10];  //记录n个字符串
    int deep;       //搜索深度
    char DNA[4]={'A','T','C','G'};    //四种可能
    int Max(int x,int y){     
    	if(x>y)return x;
    	else return y;
    }
    void Dfs(int index,int len[]){
    	if(index>deep)return;        //大于限制的深度,不用往下搜索  
    	int i,j,maxx=0;       //预计还要匹配的字符串的最大长度  
    	for(i=0;i<n;i++){
    		maxx=Max(strlen(str[i])-len[i],maxx);
    	}
    	if(maxx==0){ //条件全部满足即为最优解 
    		ans=index;
    		return;
    	}
    	if(index+maxx>deep)      //剪枝 
    		return;             //当前的深度+最少还有加深的深度是否大于限制的长度,若是,则退回
    	for(i=0;i<4;i++){
    		int flag=0;
    		int pos[10];
    		for(j=0;j<n;j++){
    			if(str[j][len[j]]==DNA[i]){//表示该字母可以往下搜索
    				flag=1;
    				pos[j]=len[j]+1;
    			}
    			else pos[j]=len[j];
    		}
    		if(flag)Dfs(index+1,pos);
    		if(ans!=-1)return;    //已经搜到最优解 不必再往下搜
    	}
    }
    int main()
    {
    	int t,i;
    	scanf("%d",&t);
    	while(t--){
    		scanf("%d",&n);
    		deep=0;
    		for(i=0;i<n;i++){
    			scanf("%s",str[i]);
    			deep=Max(deep,strlen(str[i]));//找出最长的串的长度,作为初始时的迭代DFS的限制
    		}
    		ans=-1;
    		int pos[10]={0};    //记录n个字符串目前匹配到的位置  
    		while(1){
    			Dfs(0,pos);
    			if(ans!=-1)
    				break;
    			deep++; //加深迭代
    		}
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    CAS SSO单点登录框架学习
    [精华][推荐]CAS SSO单点登录服务端客户端学习
    [精华][推荐]CAS SSO单点登录服务端客户端实例
    CAS SSO单点登录实例
    微服务、分布式、云架构构建电子商务平台
    java分布式电子商务云平台b2b b2c o2o需要准备哪些技术??
    C语言 全局变量、静态全局变量、局部变量、静态局部变量
    使用Shader制作loading旋转动画
    PureMVC 官方文档翻译(一)
    极致21点开发DAY4
  • 原文地址:https://www.cnblogs.com/iss-ue/p/12679637.html
Copyright © 2020-2023  润新知