题目意思:hdu1547,Bubble Shooter游戏,新射出的球和已有的球能连成三个及以上的会爆炸,爆炸后有些球和最上层的球失去连接,这些球也会爆炸。问射出某个球后,图上如果爆炸后还剩多少颗球。
解题思路:首先算出图上的球的数量total,全部球vis标记为0,然后两次dfs: 1.先把新射出去球标记为1,从这个位置开始dfs,六个方向同颜色的都标记为1,算出总共可以连接的同颜色球的数量cnt1; 2.如果cnt1小于3则根本不会爆炸,输出0结束; 2.如果cnt1>=3则设定cnt2=0,循环最顶端行的球,如果该球不为空且vis为0则cnt2++,从该球的位置六个方向dfs,有不为空的位置则cnt2++继续dfs。统计出所有与最顶端行不爆炸的球有连接的球的数量cnt2。 4.total-cnt2为爆炸的球的数量
代码明细:
//probID: hdu1547
//author: WiselyQY
//date: 2021-01-02
#include <bits/stdc++.h>
using namespace std;
int H,W,h,w,vis[105][105],total,cnt1,cnt2;
char g[105][105];
const int dx[2][6]={{0,0,-1,-1,1,1},{0,0,-1,-1,1,1}}, dy[2][6]={{-1,1,0,1,0,1},{-1,1,-1,0,-1,0}};//偶数行和奇数行六个方向的位置
int in(int x, int y)
{
if(x%2) return x>=1 && x<=H && y>=1 && y<=W;//奇数行width不能大于W
else return x>=1 && x<=H && y>=1 && y<=W-1;//偶数行width不能大于W-1
}
//统计与新射出的球连接的同颜色的球的数量且标记为1
void dfs1(int x, int y)
{
for(int i=0; i<6; i++)
{
int nx=x+dx[x%2][i], ny=y+dy[x%2][i];//偶数行和奇数行的六个方向
if(in(nx,ny) && !vis[nx][ny] && g[nx][ny]==g[h][w])
{
cnt1++;
vis[nx][ny]=1;
dfs1(nx,ny);
}
}
}
//统计出所有与最顶端行不爆炸的球有连接的球的数量
void dfs2(int x, int y)
{
for(int i=0; i<6; i++)
{
int nx=x+dx[x%2][i], ny=y+dy[x%2][i];
if(in(nx,ny) && !vis[nx][ny] && g[nx][ny]!='E')
{
cnt2++;
vis[nx][ny]=2;
dfs2(nx,ny);
}
}
}
int main()
{
clock_t start,end;
start=clock();
#ifndef ONLINE_JUDGE
freopen(R"(D:\code\hdu\1547_2\in.txt)","r",stdin);
#endif
while(cin>>H>>W>>h>>w)
{
total=0;
for(int i=1; i<=H; i++)
{
int k=(i%2==1)?W:W-1;
for(int j=1; j<=k; j++)
{
cin>>g[i][j];
if(g[i][j]!='E') total++;
}
}
memset(vis,0,sizeof(vis));
vis[h][w]=1;
cnt1=1;
dfs1(h,w);
if(cnt1<3) cout<<"0"<<endl;//与新射出的球连接的同颜色的球的数量小于3,则根本不会爆炸,输出0结束
else
{
cnt2=0;
for(int i=1; i<=W; i++)
if(!vis[1][i] && g[1][i]!='E') //统计出所有与最顶端行不爆炸的球有连接的球的数量cnt2
{
cnt2++;
vis[1][i]=2;
dfs2(1,i);
}
cout<<total-cnt2<<endl;
}
}
end=clock();
//printf("time=%lfs\n",(double)(end-start)/1000);
return 0;
}