【jzoj2218】【BFS】房间开灯(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个房间里的灯。

来源/作者: 2017 省中集训


解题思路

BFS

先用邻接表存储开关,每个队列里的房间把能开的灯都开了,再把队列里的点都找一遍,有没有亮的房间扩展


#include<iostream>
#include<cstdio>
using namespace std;
const int way[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
struct DT{
	int tox,toy,next;
}a[20200];
int n,m,x1,y1,x2,y2,h,t,num,Gun;
int head[200][200],f[200][200],v[10100][2],light[200][200];
bool check(int x,int y){
	return (x>0&&x<=n&&y>0&&y<=n);
}
void bfs(){
	f[1][1]=1,h=0,t=1,v[1][0]=1,v[1][1]=1,light[1][1]=1; 
	while(h++<t){
	    //**************************************
		int z=head[v[h][0]][v[h][1]];
		while(z){
			light[a[z].tox][a[z].toy]=1;
			z=a[z].next;
		}
		//把灯开了//*****************************
		for(int i=1;i<=h;i++)
		    for(int j=0;j<4;j++){
		    	int xx=v[i][0]+way[j][0],yy=v[i][1]+way[j][1];
		    	if(check(xx,yy)&&!f[xx][yy]&&light[xx][yy]){
		    		v[++t][0]=xx,v[t][1]=yy;
		    		f[xx][yy]=1;
				}
			}
		//找有没有多的可以走的亮着的房间//*********
	}
}
int main(){
	freopen("light.in","r",stdin);
	freopen("light.out","w",stdout);
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++){
		scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
		a[++num].tox=x2,a[num].toy=y2,a[num].next=head[x1][y1],head[x1][y1]=num;
	}
	bfs();
	for(int i=1;i<=n;i++)
	    for(int j=1;j<=n;j++)
	        Gun+=light[i][j];
	printf("%d",Gun);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值