WEEK_7(DFS)

B3625 迷宫寻路

        一道关于dfs走迷宫的板子题,思路:从头开始走,通过尝试下一步可能走到的点判断遇到障碍物或者撞墙则跳过,并且标记走过的坐标,因为本题比较水,只用判断能不能到达终点即可,因此一旦到达终点,标志变量就可以赋1,每次对标志变量进行判断,如果可以到终点,则一直返回

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=105;
int n,m;
char mp[N][N];
int mx[5]={0,-1,1,0,0};
int my[5]={0,0,0,-1,1};
int f;
int vis[N][N];
void dfs(int x,int y)
{
	if((x==n&&y==m)||f)
	{
		f=1;
		return ;
	}
	for(int i=1;i<=4;i++)
	{
		int zx=x+mx[i],zy=y+my[i];
		if(zx<1||zy<1||zx>n||zy>m||mp[zx][zy]=='#'||vis[zx][zy])
		continue;
		vis[zx][zy]=1;
		dfs(zx,zy);
	}
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++)
	cin>>mp[i][j];
	vis[1][1]=1;
	dfs(1,1);
	if(f)
	cout<<"Yes";
	else
	cout<<"No";
}

P1706 全排列问题

每次从1开始,对每个数进行判断是否被用过,如果没有被用过就存入数组中并对其进行标记,同时将计数+1

代码:

#include<bits/stdc++.h>
using namespace std;
int n;
int vis[10];
int num[10];
void dfs(int w)
{
	if(w==n+1)
	{
		for(int i=1;i<=n;i++)
		cout<<setw(5)<<num[i];
		cout<<endl;
		return ;
	}
	for(int i=1;i<=n;i++)
	if(!vis[i])
	{
		num[w]=i;
		vis[i]=1;
		dfs(w+1);
		vis[i]=0;
	}
}
int main()
{
	cin>>n;
	dfs(1);
}

P1451 求细胞数量

本题思路挺好想的,从起点开始找不是0的数,找到一个就说明至少有一个细胞,然后对这个点进行dfs,找到这个点相连着的其他点,并把这个点和其他相连着的不是0的点都转变成0

代码:

#include<bits/stdc++.h>
using namespace std;
int n,m;
const int N=105;
string s[10005];
int mp[N][N];
int vis[N][N];
int ans;
int mx[5]={0,0,0,1,-1};
int my[5]={0,1,-1,0,0};
void dfs(int x,int y)
{
	mp[x][y]=0;
	for(int i=1;i<=4;i++)
	{
		int zx=x+mx[i],zy=y+my[i];
		if(mp[zx][zy]&&!vis[zx][zy])
		{
			vis[zx][zy]=1;
			mp[zx][zy]=0;
			dfs(zx,zy);
		}
	}
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	cin>>s[i];
	for(int i=1;i<=n;i++)
	for(int j=0;j<m;j++)
	mp[i][j+1]=s[i][j]-'0';
	for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++)
	{
		vis[i][j]=1;
		if(mp[i][j])
		ans++,dfs(i,j);
	}
	cout<<ans;
}

P1219 [USACO1.5] 八皇后 Checker Challenge

通过这一题,能学到对于以某个点为中心的正反对角线很好的遍历方法,不难发现,正对角线上所有的数字(行数-列数)是相等的,为了防止有负数产生,可以再加上一个数使其变成正数,反对角线,(行数+列数)相等,再有该数所在的一行一列,那么标记也就很简单了。

这一题思路清奇,用每一行行标开始遍历,将棋子放在每一行所产生的情况中找到解,也就是说,形参 i 在本题中既作为行标,也作为摆放棋子的数量,那么代码如下:

#include<bits/stdc++.h>
using namespace std;
int n;
const int N=105;
int num,ans;
int zb[N];
int li[N];
int zdu[N];
int rdu[N];
int count=0;
void dfs(int i)
{
	if(i>n)
	{
		ans++;
		if(ans<=3)
		{
			for(int i=1;i<=n;i++)
			cout<<zb[i]<<" ";
			cout<<endl;
		}
	}
	else
	{
		for(int j=1;j<=n;j++)
		{	
			if(!li[j]&&!rdu[i+j]&&!(zdu[i-j+n]))
			{
				zb[i]=j;
				li[j]=1;
				rdu[i+j]=1;
				zdu[i-j+n]=1;
				dfs(i+1);
				li[j]=0;
				rdu[i+j]=0;
				zdu[i-j+n]=0;
			}
		}
	}
	return ;
}
int main()
{
	cin>>n;
	dfs(1);
	cout<<ans;
	return 0;
}

以下是选做题:

P1019 [NOIP2000 提高组] 单词接龙


P5440 【XR-2】奇迹


P5194 [USACO05DEC] Scales S


P1378 油滴扩展

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值