HDU 2531 Catch him(BFS:判断是否存在路径)

HDU 2531 Catch him(BFS:判断是否存在路径)

http://acm.hdu.edu.cn/showproblem.php?pid=2531

题意:

        给你一个R*C的棋盘,但是现在不是一个格子移动了,而是多个格子组成的一个防守队员平移一个距离,但是这个组合防守队员格不可以转动身体,且身体不能触碰到O格子.最终只要身体能触碰到Q格子就算赢.

分析:

        BFS的关键在于你设计一个结构保存棋牌的每一步状态,然后根据当前状态扩展出它的所有可行不重复后继状态.最终通过判断后继是否终态来结束BFS.

       就拿这道题来说,棋牌上共4种点,但是只有D点是会动的,我们只需要保存下所有D点的坐标,即可完整保存整个棋盘的状态.所以采用如下结构来表示每个状态:

struct Node

{

    int r[21],c[21];

    int dist;

};

       正常来说,D格子最多有20个,你要判重这种具有20个坐标的状态,只能用hash了,不可能设一个20维的vis数组来判重.但是这里要注意:D球员只能平移,也就是说D格子之间的相对位置是不变的,我们只要知道最左上角的D格子,其他D格子的位置就也知道了.所以我们只需要用一个vis[r][c]来判断防守球员最左上角的那个格子是否出现在(r,c)过即可.

AC代码:

<span style="font-size:18px;">#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxn=105;
int dr[]={-1,1,0,0};
int dc[]={0,0,-1,1};
int R,C,size;
char map[maxn][maxn];
bool vis[maxn][maxn];
struct Node
{
    int r[21],c[21];
    int dist;
}start;
int BFS()
{
    queue<Node> Q;
    memset(vis,0,sizeof(vis));
    Q.push(start);
    while(!Q.empty())
    {
        Node node=Q.front(); Q.pop();
        for(int d=0;d<4;d++)
        {
            int i;
            Node p=node;
            p.dist++;
            for(i=0;i<size;i++)
            {
                p.r[i] += dr[d];
                p.c[i] += dc[d];
                if(p.r[i]<0||p.r[i]>=R||p.c[i]<0||p.c[i]>=C) break;
                if(map[p.r[i]][p.c[i]]=='O') break;
            }
            if(i!=size) continue;       //非法
            if(vis[p.r[0]][p.c[0]]) continue;
            for(i=0;i<size;i++) if(map[p.r[i]][p.c[i]]=='Q') return p.dist;
            vis[p.r[0]][p.c[0]]=true;
            Q.push(p);
        }
    }
    return -1;
}
int main()
{
    while(scanf("%d%d",&R,&C)==2&&R)
    {
        size=0;
        for(int i=0;i<R;i++)
        for(int j=0;j<C;j++)
        {
            scanf(" %c",&map[i][j]);
            if(map[i][j]=='D')
            {
                start.r[size]=i;
                start.c[size++]=j;
            }
        }
        start.dist=0;
        int ans=BFS();
        if(ans==-1) printf("Impossible\n");
        else printf("%d\n",ans);
    }
    return 0;
}
</span>


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值