HDU1547_Bubble Shooter_泡泡龙_广搜

题目大意: 给你一个类似于地图的东西,然后奇数行的个数比偶数行的个数多一,就跟QQ上的泡泡龙游戏一样吧,,然后题目一开始给的你的图里面就包括了你已经射击了的那个球,并给出了这个地图的长,宽,还有起始点的坐标。你射击的泡泡中,如果有三个以上的泡泡颜色相同,那么它们就会爆炸,还有爆炸后,如果有泡泡跟从(上面往下数)第一行的泡泡没有直接或者间接相连,那么也会爆炸,求最后爆炸了多少个泡泡(题目输入中,小写字母表示泡泡的颜色,‘E’表示这个位置一开始就没有泡泡,这一点很重要啊); 解题思路: 一共要搜索两次,第一次从你射击的那个泡泡开始搜索,第二次从第一行开始搜索连通的地方,排除掉中途因为没有连接顶层而爆炸的泡泡。注意,如果第一次搜索到的相同颜色的泡泡的个数小于3,那么就要把它们标志回去visited[][]=false;最后用其实泡泡总数tal-最后搜索跟顶层相连通的泡泡数量remainder=爆炸的个数explode. 吐吐槽: wa了很多次,因为没有注意到你射击的那个泡泡题目已经给出,还有,从顶层搜索连通的时候,忘记了有'E'这种东东存在的情况,归根结底还是题目没有看清楚。。题目没看清楚,还做个毛题啊。。为了快,最后反而变得很慢很慢。 丑陋代码:
#include
#include
const int MAX=105;
using namespace std;
typedef struct node
{
	int x,y;
	int num;
}N;
int h,w;

char map[MAX][MAX];
bool visited[MAX][MAX];
int dir2[6][2]={{-1,0},{-1,1},{0,1},{1,1},{1,0},{0,-1}};//偶数行,右边
int dir1[6][2]={{-1,0},{0,1},{1,0},{1,-1},{0,-1},{-1,-1}};//奇数行,左边
int bfs(int x,int y,int num)//搜连通
{
	queueQ;
	N cur,pre;
	pre.x=x,pre.y=y;
	if(visited[pre.x][pre.y]==true)
		return 0;
	visited[pre.x][pre.y]=true;
	Q.push(pre);
	while(!Q.empty())
	{
		pre=Q.front();
		Q.pop();
		if(pre.x%2)//奇数行
		{
			for(int i=0;i<6;i++)
			{
				cur=pre;
				cur.x+=dir1[i][0];
				cur.y+=dir1[i][1];
				if(cur.x>=1 && cur.x<=h && cur.y>=1 && cur.y<=w
					&& visited[cur.x][cur.y]==false && map[cur.x][cur.y]!='E' && map[cur.x][cur.y]!='\0')
				{
					visited[cur.x][cur.y]=true;
					num++;
					Q.push(cur);
				}
			}
		}
		else//偶数行
		{
			for(int i=0;i<6;i++)
			{
				cur=pre;
				cur.x+=dir2[i][0];
				cur.y+=dir2[i][1];
				if(cur.x>=1 && cur.x<=h && cur.y>=1 && cur.y<=w
					&& visited[cur.x][cur.y]==false && map[cur.x][cur.y]!='E' && map[cur.x][cur.y]!='\0')
				{
					visited[cur.x][cur.y]=true;
					num++;
					Q.push(cur);
				}
			}
		}
	}
	return num;
}

int bfs1(int x,int y,int num)//先搜射击的地方
{
	
	queueQ;
	N cur,pre;
	pre.x=x,pre.y=y;
	pre.num=1;
	visited[pre.x][pre.y]=true;
	Q.push(pre);
	char ch=map[pre.x][pre.y];
	while(!Q.empty())
	{
		pre=Q.front();
		Q.pop();
		if(pre.x%2)//奇数行
		{
			for(int i=0;i<6;i++)
			{
				cur=pre;
				cur.x+=dir1[i][0];
				cur.y+=dir1[i][1];
				if(cur.x>=1 && cur.x<=h && cur.y>=1 && cur.y<=w
					&& visited[cur.x][cur.y]==false && map[cur.x][cur.y]==ch && map[cur.x][cur.y]!='\0')
				{
					visited[cur.x][cur.y]=true;
					num++;
					Q.push(cur);
				}
			}
		}
		else//偶数行
		{
			for(int i=0;i<6;i++)
			{
				cur=pre;
				cur.x+=dir2[i][0];
				cur.y+=dir2[i][1];
				if(cur.x>=1 && cur.x<=h && cur.y>=1 && cur.y<=w
					&& visited[cur.x][cur.y]==false && map[cur.x][cur.y]==ch && map[cur.x][cur.y]!='\0')
				{
					visited[cur.x][cur.y]=true;
					num++;
					Q.push(cur);
				}
			}
		}
	}
	return num;
}
void init()
{
	memset(visited,false,sizeof(visited));
}
int main(void)
{
	int x,y;
	while(scanf("%d%d%d%d",&h,&w,&x,&y)==4)
	{
		int shoot_num,tal=0;
		for(int i=1;i<=h;i++)
		{
			scanf("%s",map[i]+1);
			if(i%2==0)
			{
				map[i][w]='E';
				map[i][w+1]='\0';
			}
			for(int j=1;j<=w;j++)
				if(map[i][j]!='E')
					tal++;
		}
		init();
		shoot_num=bfs1(x,y,1);
		if(shoot_num<3)
		{
			memset(visited,false,sizeof(visited));//如果射击不中的,都标志为false
		}
		int temp=0,remainder=0;
		for(int j=1;j<=w;j++)
		{
			if(visited[1][j]==false && map[1][j]!='E')
			{
				temp=bfs(1,j,1);//搜连通,即掉落的个数
				remainder+=temp;
			}
		}
		int explode=0;
 		explode=tal-remainder;
		printf("%d\n",explode);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/cchun/p/2520205.html