ACM第七周

本文章主要记录第七周做题的思路。如有错误,请大佬斧正。若大佬有更好的思路,也请指教。

本周涉及DFS深度优先搜索

一、B3625 迷宫寻路

思路:

        跟第六周的电梯很像,用BFS可以轻松搞定。

代码:

#include <bits/stdc++.h>
using namespace std;
struct pos{
	int xx,yy;
	char vv;
};
pos f[102][102],cur,nex;
int a[4]={0,0,1,-1},
	b[4]={1,-1,0,0};
int n,m,no=0;
queue<pos> qu;

int main() 
{
	cin>>n>>m;
	for(int x=0;x<=n+1;x++)
	{
		for(int y=0;y<=m+1;y++)
			f[x][y].vv='#';
	}
	for(int x=1;x<=n;x++)
	{
		for(int y=1;y<=m;y++)
		{
			cin>>f[x][y].vv;
			f[x][y].xx=x;
			f[x][y].yy=y;
		}
	}
	
	qu.push(f[1][1]);
	while(!qu.empty())
	{
		cur.vv=qu.front().vv;
		cur.xx=qu.front().xx;
		cur.yy=qu.front().yy;
		qu.pop();
		//到达
		if(cur.xx==n&&cur.yy==m)
		{
			cout<<"Yes";
			return 0;
		}
		for(int i=0;i<4;i++)
		{
			//四处找路
			if(f[cur.xx+a[i]][cur.yy+b[i]].vv=='.')
			{
				
				//继续走
				f[cur.xx+a[i]][cur.yy+b[i]].vv='#';
				qu.push(f[cur.xx+a[i]][cur.yy+b[i]]);
			}
		}
	}
	cout<<"No";
}

二、P1706 全排列问题

思路:

        本题用DFS,会一条路走到黑(如图1),而BFS会一层一层地搜索(如图2)

图1:

图2:

        值得注意的是,DFS的回溯确实是一个难点。return返回的是调用这个函数的位置。举个例子:假设dfs(4)要return,那它会回到dfs(3),而dfs(3)又是dfs(2)调用的,所以又会回到dfs(2),然后回到dfs(1).这是正常情况。但下面代码有点特殊,就是for循环会打断dfs的回溯。

代码:

#include <bits/stdc++.h>
using namespace std;
int step,n,num[10]={0},vis[10]={0};
void dfs(int step)
{
	if(step==n+1)// 如果达到目标状态,输出结果并返回
	{
		for(int i=1;i<=n;i++)
		{
			cout<<setw(5)<<num[i];
		}
		cout<<endl;
		return;//回溯,回到调用的位置(若上个位置也是被调用的,则会一直在嵌套中一直返回上一级,直到被for打断)
	}
	for(int i=1;i<=n;i++)
	{
		if(vis[i]==0)
		{
			vis[i]=1;
			num[step]=i;
			dfs(step+1);// 继续向下一个状态进行搜索
			
			vis[i]=0;// 回溯,将当前元素的访问状态恢复
		}
	}
}
int main() 
{
	cin>>n;
	dfs(1);
}

三、P1451 求细胞数量

思路:

        BFS的搜索,没啥说的。

代码:

#include <bits/stdc++.h>
using namespace std;
struct pos{
	int xx,yy;
	char vv;
};
pos f[102][102],cur;
int a[4]={0,0,1,-1},
	b[4]={1,-1,0,0};
int n,m,no=0;
queue<pos> qu;
void bfs(int x,int y)
{
	if(f[x][y].vv=='0')
	{
		return;
	}

	qu.push(f[x][y]);
	while(!qu.empty())
	{
		f[x][y].vv=='0';
		cur=qu.front();
		qu.pop();
		
		for(int i=0;i<4;i++)
		{
			//四处找
			if(f[cur.xx+a[i]][cur.yy+b[i]].vv!='0')
			{
				//找到
				f[cur.xx+a[i]][cur.yy+b[i]].vv='0';
				qu.push(f[cur.xx+a[i]][cur.yy+b[i]]);
			}
			
		}
	}
	no++;
	return;
}
int main() 
{
	cin>>n>>m;
	for(int x=0;x<=n+1;x++)
	{
		for(int y=0;y<=m+1;y++)
			f[x][y].vv='0';
	}
	for(int x=1;x<=n;x++)
	{
		for(int y=1;y<=m;y++)
		{
			cin>>f[x][y].vv;
			f[x][y].xx=x;
			f[x][y].yy=y;
		}
	}
	for(int x=1;x<=n;x++)
	{
		for(int y=1;y<=m;y++)
		{
			bfs(x,y);
		}
	}
	cout<<no;
}

四、P1219 [USACO1.5] 八皇后 Checker Challenge

思路:

        DFS的框架与第二题是一样的。

        但关于两个皇后是否同行、同列、同对角线的判断还是很有意思的,尤其是是否在同一对角线的判断(当然主要是我见识太少了)。

代码:

#include<bits/stdc++.h>
using namespace std;
int n,x,no=0,tem[105];
bool sh[105],xi[105],fxi[105];//判断同行、列、对角线
void dfs(int x)
{
	//判断满足条件
	if(x>n)
	{
		no++;//计数
		if(no<=3)
		{
			for(int xx=1;xx<=n;xx++)
			{
					cout<<tem[xx]<<" ";
			}
			cout<<endl;
		}
		return;
	}
	//循环列数,找地放皇后
	for(int i=1;i<=n;i++)
	{
		if(!sh[i]&&!xi[x-i+n]&&!fxi[x+i])
		{
			tem[x]=i;
			sh[i]=1;//标记
			xi[x-i+n]=1;
			fxi[x+i]=1;
			//找到后,行数+1
			dfs(x+1);
			//回溯,将bool还原
			sh[i]=0;
			xi[x-i+n]=0;
			fxi[x+i]=0;
		}	
	}
}

int main()
{
	cin>>n;
	dfs(1);
	cout<<no;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值