《算法竞赛从入门到进阶》心得及相关题解013--dfs--hdu1547


题目意思: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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值