题解 P2845 【[USACO15DEC]Switching on the Lights S】
• 基本思路
很明显,这是一篇 BFS 的题,但 BFS 能解决的 DFS 也可以。
从
但是我们来看一下下面这个样例:
3 4
1 1 1 2
1 2 2 1
2 1 1 3
1 3 3 1
我们可以模拟到,当
1 1 1
1 0 0
X 0 0
很多 dalao 都表示应该往回搜,但本蒟蒻不是很懂其原理,实际上我们可以反复 DFS,期间
同样的样例,在第二次 DFS 搜到
• 具体代码
#include<iostream>
#include<cstdio>
using namespace std;
int n,k,x,y,a,b,ans,ans1;
//ans记录能打开灯的房间数量
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
bool mark[101][101],z[101][101];
//mark[i][j]表示(i,j)房间的电灯状态
//z[i][j]表示(i,j)房间是否走过
struct l{
int x[10001],y[10001],top;
}m[101][101];
//x[i]和y[i]分别表示当前房间第i个能控制的房间坐标
//top表示当前房间能控制的房间数量
void dfs(int x,int y){
for(int i=1;i<=m[x][y].top;i++)
mark[m[x][y].x[i]][m[x][y].y[i]]=1;
//将当前房间能打开的都打开
for(int i=0;i<4;i++)
if(x+dx[i]>=1&&x+dx[i]<=n&&y+dy[i]>=1&&y+dy[i]<=n&&mark[x+dx[i]][y+dy[i]]&&!z[x+dx[i]][y+dy[i]]){
z[x+dx[i]][y+dy[i]]=1;
dfs(x+dx[i],y+dy[i]);
}
}
int main(){
mark[1][1]=1,z[1][1]=1;
cin>>n>>k;
for(int i=1;i<=k;i++){
cin>>x>>y>>a>>b;
m[x][y].x[++m[x][y].top]=a,m[x][y].y[m[x][y].top]=b;
//记录(x,y)房间能控制的房间坐标
}
dfs(1,1);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(mark[i][j])ans++;
//统计所有开着灯的房间数量
while(ans!=ans1){
ans1=ans;//ans1存储上一次DFS的值
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
z[i][j]=0;
dfs(1,1);
ans=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(mark[i][j])ans++;
//更新ans的值
}
cout<<ans;
return 0;
}