搜索(深搜&广搜)

我记得在遥远的2017年,我会敲的搜索也只有暴力枚举了。那个时候的我深搜刚会一丢丢,所以也只配切切水题,然而经常死循环RE那是肯定的。如今的我因为在多次比赛中都死于搜索,那就必须得认真磕一下了。

其实是这样的:我眼里认为的暴力就真的只是暴力,暴力无非就两种:枚举打表和模拟。然而在这么多次比赛后,我总能听到那些dalao在那边说,这道题么暴力可以拿多少多少分。我听了一脸懵逼。我怎么就一分都拿不到。这个时候我才如梦初醒,发现他们说的暴力其实都是指深搜。于是我就不得不去学深搜了。

然而,事实上,我发现深搜真的很简单。

于是,我切了好多题库第三页上的搜索题,有深搜的,也有广搜的。

我还记得那个时候稚嫩的我连那么简单的广搜都听不懂,还是涵神讲的。我竟然都听不懂。现在我发现广搜也就那样。所以我估计那时候我是因为对队列的理解不够深刻导致的。

ok,板子来几个。

T1细胞染色

直接深搜:从每一个非0的数开始搜,如果碰到与它相邻的非0的数,那就把它变成0。

#include<bits/stdc++.h>
using namespace std;
int m,n,ans;
char a[110][110];
string s;
inline int read()
{
	int num=0,flag=1;
	char c=getchar();
	for (;c<'0'||c>'9';c=getchar())
	if (c=='-') flag=-1;
	for (;c>='0'&&c<='9';c=getchar())
	num=(num<<3)+(num<<1)+c-48;
	return num*flag;
}
void dfs(int x,int y)
{
	if (a[x][y]=='0') return;
	a[x][y]='0'; 
	dfs(x-1,y);
	dfs(x+1,y);
	dfs(x,y-1);
	dfs(x,y+1);
}
int main()
{
	m=read();
	n=read();
	for (int i=0;i<=m+1;++i)
	for (int j=0;j<=n+1;++j)
	a[i][j]='0';
	for (int i=1;i<=m;++i) 
	{
		for (int j=1;j<=n;++j)
		a[i][j]=getchar();
		getline(cin,s);
	}
	for (int i=1;i<=m;++i)
	for (int j=1;j<=n;++j)
	if (a[i][j]!='0')
	{
		ans++;
		dfs(i,j);
	}
	printf("%d\n",ans);
	return 0;
}

T2迷宫

深搜+回溯:要多开一个b数组标记该点是否被访问过,如果已经访问过了再去访问就会死循环。

#include<bits/stdc++.h>
using namespace std;
int n,m,t,sx,sy,fx,fy,x,y,ans;
bool a[10][10],b[10][10];
inline int read()
{
	int num=0,flag=1;
	char c=getchar();
	for (;c<'0'||c>'9';c=getchar())
	if (c=='-') flag=-1;
	for (;c>='0'&&c<='9';c=getchar())
	num=(num<<3)+(num<<1)+c-48;
	return num*flag;
}
void dfs(int x,int y)
{
	if (x<1||x>n||y<1||y>m||a[x][y]||b[x][y]) return;
	if (x==fx&&y==fy)
	{
		ans++;
		return;
	}
	b[x][y]=true;
	dfs(x-1,y);
	dfs(x+1,y);
	dfs(x,y-1);
	dfs(x,y+1);
	b[x][y]=false;
}
int main()
{
	n=read();
	m=read();
	t=read();
	sx=read();
	sy=read();
	fx=read();
	fy=read();
	for (int i=1;i<=t;++i)
	{
		x=read();
		y=read();
		a[x][y]=true;
	}
	dfs(sx,sy);
	printf("%d\n",ans);
	return 0;
}

T3八皇后

这道题调了好久,用了好多不同的方法来写,结果反正就是那些小问题。最近发现我调题都可以调好久,估计又fuzao了。

#include<bits/stdc++.h>
using namespace std;
int n,ans,a[100],b[100][100];
inline int read()
{
	int num=0,flag=1;
	char c=getchar();
	for (;c<'0'||c>'9';c=getchar())
	if (c=='-') flag=-1;
	for (;c>='0'&&c<='9';c=getchar())
	num=(num<<3)+(num<<1)+c-48;
	return num*flag;
}
void dfs(int x,int y)
{
	a[x]=y;
	if (x==n)
	{
		ans++;
		if (ans<=3)
		{
			for (int i=1;i<=n;++i)
			if (i!=n) printf("%d ",a[i]);
			else printf("%d",a[i]);
			printf("\n");
		}
		return;
	}
	for (int i=1;i<=n;++i)
	if (b[x+1][i]==0)
	{
		for (int j=x+2;j<=n;++j)
		{
			if (x+1+i-j>=1) b[j][x+1+i-j]++;
			b[j][i]++;
			b[j][i-x-1+j]++;
		}
		dfs(x+1,i);
		for (int j=x+2;j<=n;++j)
		{
			if (x+1+i-j>=1) b[j][x+1+i-j]--;
			b[j][i]--;
			b[j][i-x-1+j]--;
		}
	}
}
int main()
{
	n=read();
	dfs(0,0);
	printf("%d\n",ans);
	return 0;
}

T4青铜莲花池

BFS八个方向。发现bfs的板子都差不多:首先,该进队的都进队。然后,取队头,向几个方向都遍历一次。如果符合要求,该点进队,ans数组更新。当然,这里也需要开一个b数组来存储当前点是否已经入过队。

#include<bits/stdc++.h>
using namespace std;
int m,n,m1,m2,a[35][35],sx,sy,fx,fy,ans[35][35];
int dx[10],dy[10];
bool b[35][35];
struct queue
{
	int x,y;
}
q[1010];
inline int read()
{
	int num=0,flag=1;
	char c=getchar();
	for (;c<'0'||c>'9';c=getchar())
	if (c=='-') flag=-1;
	for (;c>='0'&&c<='9';c=getchar())
	num=(num<<3)+(num<<1)+c-48;
	return num*flag;
}
void bfs()
{
	int head=1,tail=0;
	q[++tail].x=sx;
	q[tail].y=sy;
	b[sx][sy]=true;
	while (head<=tail)
	{
		int kx=q[head].x,ky=q[head++].y;
		for (int i=0;i<8;++i)
		{
			int xx=kx+dx[i],yy=ky+dy[i];
			if ((a[xx][yy]==1||a[xx][yy]==4)&&!b[xx][yy])
			{
				q[++tail].x=xx;
				q[tail].y=yy;
				ans[xx][yy]=ans[kx][ky]+1;
				b[xx][yy]=true; 
			}
		}
	}	
}
int main()
{
	m=read();
	n=read();
	m1=read();
	m2=read();
	for (int i=1;i<=m;++i)
	for (int j=1;j<=n;++j)
	{
		a[i][j]=read();
		if (a[i][j]==3)
		{
			sx=i;
			sy=j;
		}
		if (a[i][j]==4)
		{
			fx=i;
			fy=j;
		}
	}
	dx[0]=-m1;dy[0]=-m2;
	dx[1]=m1;dy[1]=-m2;
	dx[2]=-m1;dy[2]=m2;
	dx[3]=m1;dy[3]=m2;
	dx[4]=-m2;dy[4]=-m1;
	dx[5]=m2;dy[5]=-m1;
	dx[6]=-m2;dy[6]=m1;
	dx[7]=m2;dy[7]=m1;
	bfs();
	printf("%d\n",ans[fx][fy]);
	return 0;
}

T5爱心企鹅

7.19牛客②I
广搜板子↓

#include<bits/stdc++.h>
using namespace std;
int dx1[4]={1,0,0,-1},dy1[4]={0,-1,1,0};
int dx2[4]={1,0,0,-1},dy2[4]={0,1,-1,0};
char s[4]={'D','L','R','U'};
char a[50][50],b[50][50],u,v,x,y,ans[410];
int c[50][50][50][50],t;
struct acm
{
	int u,v,x,y;
	char d;
}
f[50][50][50][50];
queue<acm> q;
inline int read()
{
	int num=0,flag=1;
	char c=getchar();
	for (;c<'0'||c>'9';c=getchar())
	if (c=='-') flag=-1;
	for (;c>='0'&&c<='9';c=getchar())
	num=(num<<3)+(num<<1)+c-48;
	return num*flag;
}
void bfs()
{
	acm st{20,20,20,1};
	q.push(st);
	while (q.size())
	{
		acm now=q.front();
		q.pop();
		for (int k=0;k<4;++k)
		{
			acm nxt{now.u+dx1[k],now.v+dy1[k],now.x+dx2[k],now.y+dy2[k]};
			if (nxt.u<1||nxt.v<1||nxt.u>20||nxt.v>20||a[nxt.u][nxt.v]=='#')
			{
				nxt.u=now.u;
				nxt.v=now.v;
			}
			if (nxt.x<1||nxt.y<1||nxt.x>20||nxt.y>20||b[nxt.x][nxt.y]=='#')
			{
				nxt.x=now.x;
				nxt.y=now.y;
			}
			if (!c[nxt.u][nxt.v][nxt.x][nxt.y]&&(nxt.u!=20||nxt.v!=20||nxt.x!=20||nxt.y!=1))
			{
				q.push(nxt);
				c[nxt.u][nxt.v][nxt.x][nxt.y]=c[now.u][now.v][now.x][now.y]+1;
				f[nxt.u][nxt.v][nxt.x][nxt.y].u=now.u;
				f[nxt.u][nxt.v][nxt.x][nxt.y].v=now.v;
				f[nxt.u][nxt.v][nxt.x][nxt.y].x=now.x;
				f[nxt.u][nxt.v][nxt.x][nxt.y].y=now.y;
				f[nxt.u][nxt.v][nxt.x][nxt.y].d=s[k];
			}
			if (nxt.u==1&&nxt.v==20&&nxt.x==1&&nxt.y==1)
			{
				printf("%d\n",c[nxt.u][nxt.v][nxt.x][nxt.y]);
				a[nxt.u][nxt.v]='A';
				b[nxt.x][nxt.y]='A';
				while (nxt.u!=20||nxt.v!=20||nxt.x!=20||nxt.y!=1)
				{
					ans[++t]=f[nxt.u][nxt.v][nxt.x][nxt.y].d;
					u=f[nxt.u][nxt.v][nxt.x][nxt.y].u;
					v=f[nxt.u][nxt.v][nxt.x][nxt.y].v;
					x=f[nxt.u][nxt.v][nxt.x][nxt.y].x;
					y=f[nxt.u][nxt.v][nxt.x][nxt.y].y;
					nxt.u=u;
					nxt.v=v;
					nxt.x=x;
					nxt.y=y;
					a[nxt.u][nxt.v]='A';
					b[nxt.x][nxt.y]='A';
				}
				for (int i=t;i>=1;--i)
				putchar(ans[i]);
				printf("\n");
				for (int i=1;i<=20;++i)
				{
					for (int j=1;j<=20;++j)
					putchar(a[i][j]);
					printf(" ");
					for (int j=1;j<=20;++j)
					putchar(b[i][j]);
					printf("\n");
				}
				exit(0);
			}
		}
	}
}
int main()
{
	//freopen(".in","r",stdin);
	//freopen(".out","w",stdout);
	for (int i=1;i<=20;++i)
	{
		for (int j=1;j<=20;++j)
		{
			a[i][j]=getchar();
			while (a[i][j]!='.'&&a[i][j]!='#')
			a[i][j]=getchar();
		}
		for (int j=1;j<=20;++j)
		{
			b[i][j]=getchar();
			while (b[i][j]!='.'&&b[i][j]!='#')
			b[i][j]=getchar();
		}
	}
	bfs();
	fclose(stdin);
	fclose(stdout);
	return 0;
}

T6水管

7.17牛客①E
广搜加强↓

#include<bits/stdc++.h>
using namespace std;
int T,n,m,a[1005][1005],x,y,id,d,t;
bool b[1005][1005][6][4];
map<char,int> s;
struct acm
{
	int x,y,id,d;
}
f[1005][1005][6][4],c[20000010];
queue<acm> q;
inline int read()
{
	int num=0,flag=1;
	char c=getchar();
	for (;c<'0'||c>'9';c=getchar())
	if (c=='-') flag=-1;
	for (;c>='0'&&c<='9';c=getchar())
	num=(num<<3)+(num<<1)+c-48;
	return num*flag;
}
void add(acm nxt,acm now)
{
	q.push(nxt);
	b[nxt.x][nxt.y][nxt.id][nxt.d]=true;
	f[nxt.x][nxt.y][nxt.id][nxt.d].x=now.x;
	f[nxt.x][nxt.y][nxt.id][nxt.d].y=now.y;
	f[nxt.x][nxt.y][nxt.id][nxt.d].id=now.id;
	f[nxt.x][nxt.y][nxt.id][nxt.d].d=now.d;
}
void bfs()
{
	while (q.size())
	q.pop();
	if (a[1][1]<=3)
	{
		acm st{1,1,1,s['R']};
		q.push(st);
		b[st.x][st.y][st.id][st.d]=true;
	}
	else
	{
		acm st{1,1,5,s['D']};
		q.push(st);
		b[st.x][st.y][st.id][st.d]=true;
	}
	while (q.size())
	{
		acm now=q.front();
		q.pop();
		if (now.d==s['U'])
		{
			if (a[now.x-1][now.y]<=3)
			{
				acm nxt1{now.x-1,now.y,2,s['R']};
				acm nxt2{now.x-1,now.y,3,s['L']};
				if (~a[nxt1.x][nxt1.y+1]&&!b[nxt1.x][nxt1.y][nxt1.id][nxt1.d]) add(nxt1,now);
				if (~a[nxt2.x][nxt2.y-1]&&!b[nxt2.x][nxt2.y][nxt2.id][nxt2.d]) add(nxt2,now);
			}
			else
			{
				acm nxt{now.x-1,now.y,5,s['U']};
				if (~a[nxt.x-1][nxt.y]&&!b[nxt.x][nxt.y][nxt.id][nxt.d]) add(nxt,now);
			}
		}
		if (now.d==s['L'])
		{
			if (a[now.x][now.y-1]<=3)
			{
				acm nxt1{now.x,now.y-1,1,s['U']};
				acm nxt2{now.x,now.y-1,2,s['D']};
				if (~a[nxt1.x-1][nxt1.y]&&!b[nxt1.x][nxt1.y][nxt1.id][nxt1.d]) add(nxt1,now);
				if (~a[nxt2.x+1][nxt2.y]&&!b[nxt2.x][nxt2.y][nxt2.id][nxt2.d]) add(nxt2,now);
			}
			else
			{
				acm nxt{now.x,now.y-1,4,s['L']};
				if (~a[nxt.x][nxt.y-1]&&!b[nxt.x][nxt.y][nxt.id][nxt.d]) add(nxt,now);
			}
		}
		if (now.d==s['R'])
		{
			if (a[now.x][now.y+1]<=3)
			{
				acm nxt1{now.x,now.y+1,0,s['U']};
				acm nxt2{now.x,now.y+1,3,s['D']};
				if (~a[nxt1.x-1][nxt1.y]&&!b[nxt1.x][nxt1.y][nxt1.id][nxt1.d]) add(nxt1,now);
				if (~a[nxt2.x+1][nxt2.y]&&!b[nxt2.x][nxt2.y][nxt2.id][nxt2.d]) add(nxt2,now);
			}
			else
			{
				acm nxt{now.x,now.y+1,4,s['R']};
				if (~a[nxt.x][nxt.y+1]&&!b[nxt.x][nxt.y][nxt.id][nxt.d]) add(nxt,now);
			}
		}
		if (now.d==s['D'])
		{
			if (a[now.x+1][now.y]==6)
			{
				t=0;
				while (now.x)
				{
					c[++t].x=now.x;
					c[t].y=now.y;
					c[t].id=now.id;
					x=f[now.x][now.y][now.id][now.d].x;
					y=f[now.x][now.y][now.id][now.d].y;
					id=f[now.x][now.y][now.id][now.d].id;
					d=f[now.x][now.y][now.id][now.d].d;
					now.x=x;
					now.y=y;
					now.id=id;
					now.d=d;
				}
				printf("YES\n");
				printf("%d\n",2*t);
				for (int i=t;i>=1;--i)
				{
					if (c[i].id==a[c[i].x][c[i].y]) printf("1 0 %d %d\n",c[i].x,c[i].y);
					else if (c[i].id-a[c[i].x][c[i].y]==1||c[i].id==0&&a[c[i].x][c[i].y]==3)
					{
						printf("1 90 %d %d\n",c[i].x,c[i].y);
						a[c[i].x][c[i].y]=c[i].id;
					}
					else if (c[i].id-a[c[i].x][c[i].y]==2||a[c[i].x][c[i].y]-c[i].id==2)
					{
						printf("1 180 %d %d\n",c[i].x,c[i].y);
						a[c[i].x][c[i].y]=c[i].id;
					}
					else
					{
						printf("1 270 %d %d\n",c[i].x,c[i].y);
						a[c[i].x][c[i].y]=c[i].id;
					}
					printf("0 %d %d\n",c[i].x,c[i].y);
				}
				return;
			}
			if (a[now.x+1][now.y]<=3)
			{
				acm nxt1{now.x+1,now.y,0,s['L']};
				acm nxt2{now.x+1,now.y,1,s['R']};
				if (~a[nxt1.x][nxt1.y-1]&&!b[nxt1.x][nxt1.y][nxt1.id][nxt1.d]) add(nxt1,now);
				if (~a[nxt2.x][nxt2.y+1]&&!b[nxt2.x][nxt2.y][nxt2.id][nxt2.d]) add(nxt2,now);
			}
			else
			{
				acm nxt{now.x+1,now.y,5,s['D']};
				if (~a[nxt.x+1][nxt.y]&&!b[nxt.x][nxt.y][nxt.id][nxt.d]) add(nxt,now);
			}
		}
	}
	printf("NO\n");
}
int main()
{
	//freopen(".in","r",stdin);
	//freopen(".out","w",stdout);
	s['U']=0;
	s['L']=1;
	s['R']=2;
	s['D']=3;
	T=read();
	while (T--)
	{
		n=read();
		m=read();
		for (int j=0;j<=m+1;++j)
		a[0][j]=-1;
		for (int i=0;i<=n+1;++i)
		a[i][0]=-1;
		for (int i=0;i<=n+1;++i)
		a[i][m+1]=-1;
		for (int j=0;j<=m+1;++j)
		a[n+1][j]=-1;
		a[n+1][m]=6;
		for (int i=1;i<=n;++i)
		for (int j=1;j<=m;++j)
		{
			a[i][j]=read();
			for (int k=0;k<6;++k)
			for (int l=0;l<4;++l)
			b[i][j][k][l]=false;
		}
		bfs();
	}
	fclose(stdin);
	fclose(stdout);
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值