房间开灯(light)
题目描述
Farmer John 最近正在修建一个巨大的包含 N×N 个房间的牲口棚,这些房间从(1,1)标号到(N,N)。由于某些原因而害怕黑暗,贝茜这头奶牛想要尽可能地开更多房间的灯。贝茜从房间(1,1)出发,这个房间是唯一一个一开始就亮着的房间。在一些房间中,她会找到一些电灯开关,这些开关她可以用来切换其他房间的灯的状态。比如,在(1,1)这个房间中可能存在一个电灯开关来控制(1,2)房间中的电灯。贝茜只能进电灯开着的房间,并且贝茜只能从房间(x,y)走到四个方向的房间(x-1,y),(x+1,y),(x,y-1)和(x,y+1)(如果在边界的话,那可能会更少)。请帮忙统计贝茜最多可以照亮多少房间。
输入
第一行两个整数 N,M(2<=N<=100,1<=M<=20,000)
下面 M 行,每行用四个整数 x,y,a,b 来表示房间(x,y)存在着可以控制房间(a,b)的灯的开关。一个房间可能有多个开关,一个房间的灯的开关可能存在于多个房间中。
输出
一行一个整数,表示贝茜最多可以照亮的房间数
样例输入
3 6
1 1 1 2
2 1 2 2
1 1 1 3
2 3 3 1
1 3 1 2
1 3 2 1
样例输出
5
提示
在这个样例中,贝茜可以使用房间(1,1)内的开关打开房间(1,2)和(1,3)的灯。然后她可以走到(1,3),使用(1,3)内的开关打开(2,1)的灯,接着可以通过(2,1)打开(2,2)的灯,然而(2,3)是黑暗的,她无法去打开(2,3)房间里的开关,因此,她最多只能打开 5个房间里的灯。
这道题我们可以用宽搜
对于怎么存边,我们可以用二维的邻接表来实现,其实是跟一维
差不多的,用一个数组来存横向的,一个来存竖向的(xx,yy);
code:
#include<cstdio>
#include<iostream>
using namespace std;
const int dx[5]={0,-1,1,0,0}; //四个方向
const int dy[5]={0,0,0,-1,1};
int fx[20010],fy[20010],tx[20010],ty[20010];
struct node
{
int tox,toy,next;
}a[20010];
int head[110][110],t=0,qx[20010],qy[20010];
int n,m;
bool dis[110][110],f[110][110];
void add(int x,int y,int x1,int y1) //邻接表
{
a[++t].tox=x1;
a[t].toy=y1;
a[t].next=head[x][y];
head[x][y]=t;
}
void bfs() //跟不同的宽搜一样
{
int h=0,t=1;
dis[1][1]=1;
f[1][1]=1;
qx[1]=1,qy[1]=1;
do
{
h++;
int tx=qx[h],ty=qy[h];
for(int i=head[tx][ty];i;i=a[i].next)//将当前房间能开的房间点亮!
dis[a[i].tox][a[i].toy]=1;
for(int i=1;i<=h;i++)
//枚举四个方向,如果房间是亮的,则以它为中心,重复以上操作。
for(int j=1;j<=4;j++)
{
int nx=qx[i]+dx[j],ny=qy[i]+dy[j];
if(nx>=1&nx<=n&&ny>=1&&ny<=n)
{
if(dis[nx][ny]==1&&f[nx][ny]==0)
{
t++;
f[nx][ny]=1;
qx[t]=nx;
qy[t]=ny;
}
}
}
}while(h<=t);
}
int main()
{
freopen("light.in","r",stdin);
freopen("light.out","w",stdout);
cin>>n>>m;
for(int i=1;i<=m;i++)
{
cin>>fx[i]>>fy[i]>>tx[i]>>ty[i];
add(fx[i],fy[i],tx[i],ty[i]);
}
bfs();
int ans=0;
for(int i=1;i<=n;i++) //判断房间是否开的灯
for(int j=1;j<=n;j++)
if(dis[i][j]==1) ans++;
cout<<ans<<endl;
return 0;
}