zoukankan      html  css  js  c++  java
  • 深搜入门题型

    好题深搜链接:数独,技巧性深搜
    抽签,多参数去重性全排列深搜
    牌型种数,组合问题深搜
    分考场,图着色型深搜
    比赛安排,匹配问题型深搜
    填数,全排列深搜,注意精度问题!!
    给图填数+回溯(最简单的模板第三题手动ac 看代码点我!
    经典全排列,但很考验格式
    5305朋友关系
    剪邮票,联通关系问题

    题目一、骨的诱惑

    这道题目还是比较粗暴的呀,不过有很多使用的小技巧适用于走迷宫类的题目。
    1、走路的方式可以用两个数组两重循环表示,如最基本的上下左右表示为
    int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
    2、设置flag,到达终点立刻令其等于1,跳出函数
    3、由于本题不走回头路,每次经过一个位置,将visit[x][y] 设为1,表示已访问,记得回溯的时候重新将visit改为0;
    4、奇偶性剪枝。这里借用大佬的一段话:
    

    1.如果当前时间即步数(step) >= T 而且还没有找到D点,则剪掉。
    2.设当前位置(x, y)到D点(dx, dy)的最短距离为s,到达当前位置(x, y)已经花费时间(步数)step,那么,如果题目要求的时间T - step < s,则剪掉。
    3. 对于当前位置(x, y),如果,(T-step-s)是奇数,则剪掉(奇偶剪枝)。
    4.如果地图中,可走的点的数目(xnum) < 要求的时间T,则剪掉(路径剪枝)。
    ————————————————
    大佬的csdn名称「chyshnu」
    原文链接:https://blog.csdn.net/chyshnu/article/details/6171758/
    最后附上我的超长暴力代码:

    #include <bits/stdc++.h>
    using namespace std;
    int l,r,T,n,m,flag;
    int vis[200][200];
    char a[200][200];
    bool gg(int x,int y)
    {
    	if(x>=0&&x<n&&y>=0&&y<m&&vis[x][y]==0)
    		return true;
    	else
    		return false;
    }
    void dfs(int x,int y,int t)
    {
    	if(t==T-1)
    	{
    		if(gg(x+1,y)&&a[x+1][y]=='D')flag=1;
    		if(gg(x-1,y)&&a[x-1][y]=='D')flag=1;
    		if(gg(x,y+1)&&a[x][y+1]=='D')flag=1;
    		if(gg(x,y-1)&&a[x][y-1]=='D')flag=1;
    		return;
    	}
    	if(gg(x+1,y)&&a[x+1][y]=='.')
    	{
    		vis[x+1][y]=1;
    		dfs(x+1,y,t+1);
    //		if(flag)
    //			return;
    		vis[x+1][y]=0;
    	}
    	if(gg(x-1,y)&&a[x-1][y]=='.')
    	{
    		vis[x-1][y]=1;
    		dfs(x-1,y,t+1);
    //		if(flag)
    //			return;
    		vis[x-1][y]=0;
    	}
    	if(gg(x,y+1)&&a[x][y+1]=='.')
    	{
    		vis[x][y+1]=1;
    		dfs(x,y+1,t+1);
    //		if(flag)
    //			return;
    		vis[x][y+1]=0;
    	}
    	if(gg(x,y-1)&&a[x][y-1]=='.')
    	{
    		vis[x][y-1]=1;
    		dfs(x,y-1,t+1);
    //		if(flag)
    //			return;
    		vis[x][y-1]=0;
    	}
    	return;
    }
    int main()
    {
    	while(cin>>n>>m>>T)
    	{
    		memset(vis,0,sizeof(vis));
    		int x,y;
    		flag=0;
    		if(T==0&&n==0&&m==0)
    			break;
    		for(int i=0;i<n;i++)
    			cin>>a[i];
    		for(int i=0;i<n;i++)
    		{
    			for(int j=0;j<m;j++)
    			{
    				if(a[i][j]=='S')
    				{
    					x=i;y=j;
    					vis[i][j]=1;
    				}
    				if(a[i][j]=='D')
    				{
    					l=i;r=j;
    				}
    			}
    		}
    		dfs(x,y,0);
    		if(flag)
    			cout<<"YES"<<endl;
    		else
    			cout<<"NO"<<endl;	
    	}
    }
    

    题目二、hdu1016素数环

    第一个独立完成的深搜啊,直接上代码。

    #include <bits/stdc++.h>
    using namespace std;
    int n,a[30],vis[30],b[30],flag=0;
    bool sushu(int a,int b)//判断是否满足和为素数
    {
    	int c=a+b,i;
    	for(i=2;i<c;i++)
    	{
    		if(c%i==0)
    			break;
    	}
    	if(i==c)
    		return true;
    	else
    		return false;
    }
    void dfs(int num)
    {
    	if(num==n+1)
    	{
    		flag=1;//这里是关键。成功了,flag应为1,提示b数组应该回溯了
    		for(int i=1;i<=num-1;i++)//打印结果
    		{
    			cout<<b[i];
    			if(i!=num-1)
    				cout<<" ";
    		}
    		cout<<endl;
    //		b[num]=0;
    		return;
    	}
    		for(int i=2;i<=n;i++)//b[i]一定为1的,所以从i=2开始
    		{
    			if(vis[i]==0&&sushu(a[i],b[num-1]))
    			{
    				if(num==n&&!sushu(a[i],b[1]))//由于圆环,最后一次判断两头
    					break;
    				vis[i]=1;
    				b[num]=a[i];
    				dfs(num+1);
    				if(flag)
    				{
    				/*	memset(b,0,sizeof(b));
    					b[1]=1;
    					flag=0;*/
    					b[num]=0;//成功了当然得刷掉上一步啊!
    					flag=0;
    				}
    				vis[i]=0;//回溯
    			}
    		}
    }
    int main()
    {
    	int z=0;
    	while(cin>>n)
    	{
    		flag=0;
    		z++;
    		cout<<"Case "<<z<<":"<<endl;
    		memset(vis,0,sizeof(vis));
    		memset(b,0,sizeof(b));
    		b[1]=1;
    		for(int i=1;i<=n;i++)
    			a[i]=i;
    		dfs(2);
    		cout<<endl;
    	}
    }
    

    题目三:hdu1015

    直接上代码。

    在这里插入代码片
    #include <bits/stdc++.h>
    using namespace std;
    char a[20],ans[6],vis[20],sk[6];//sk数组保存结果
    int l,zhi,flag=0;//flag为判断找没找到
    int cmp(char a,char b)
    {
    	return a>b;//重要的一步,排序保证第一个搜到的是结果
    }
    void dfs(int num,int sumn)//num表示第几个字符,sumn为当前总和
    {
    	if(num==6&&sumn!=zhi)
    		return;
    	if(num==6&&sumn==zhi)
    	{
    		flag=1;//标记找到
    		return;
    	}
    	for(int i=0;i<l;i++)
    	{
    		if(vis[i]==0)
    		{
    			vis[i]=1;//标记是否用过当前字符
    			sk[num-1]=a[i];
    			dfs(num+1,sumn-pow(-1,num)*pow(a[i]-'A'+1,num));
    			if(flag)///超级重要的一步。找到了直接返回呀!
    				return;
    			sk[num-1]=0;//开始蠢了。没想到回溯应该抹去SK数组
    			vis[i]=0;
    		}
    	}
    }
    int main()
    {
    	while(cin>>zhi)
    	{
    		if(zhi==0)
    			break;
    		flag=0;
    		memset(vis,0,sizeof(vis));
    		cin>>a;
    		l=strlen(a);
    		sort(a,a+l,cmp);
    		dfs(1,0);
    		if(flag)
    			cout<<sk<<endl;
    		else
    			cout<<"no solution"<<endl;
    	}
    	return 0;
    }
    
    
    
  • 相关阅读:
    面试官问你如何解决web高并发这样回答就好了
    react-native页面间传递数据的几种方式
    图片上传知识点梳理
    使用Vue CLI 3将基于element-ui二次封装的组件发布到npm
    OpenCV学习笔记09--通过cvPtr2D或指针算法绘制图形
    [code segments] OpenCV3.0 SVM with C++ interface
    LINUX设备驱动程序笔记(一)设备驱动程序简单介绍
    redis 简单安装使用
    Linux常见压缩命令
    计算机网络13--网络应用的体系结构
  • 原文地址:https://www.cnblogs.com/iss-ue/p/12679642.html
Copyright © 2011-2022 走看看