HDU 1983 Kaitou Kid - The Phantom Thief (2)

本文介绍了一种结合深度优先搜索(DFS)与广度优先搜索(BFS)的算法,用于解决一个迷宫逃脱游戏问题。游戏的目标是在限定时间内阻止角色盗取宝石并逃离。通过暴力枚举0到3个障碍位置的方法,确保角色无法完成任务。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自:http://blog.youkuaiyun.com/madrishing/article/details/7874207?locationNum=6

Problem Description
破解字迷之后,你得知Kid将会在展览开始后T分钟内盗取至少一颗宝石,并离开展馆。整个展馆呈矩形分布,划分为N*M个区域,有唯一的入口和出口(不能从出口进入,同样不能从入口出去)。由某个区域可直接移动至相邻四个区域中的一个,且最快需要一分钟。假设Kid进入放有宝石的区域即可盗取宝石,无需耗时。问至少要封锁几个区域(可以封锁放有宝石的区域,但不能封锁入口和出口)才能保证Kid无法完成任务。
 

Input
输入的第一行有一个整数C,代表有C组测试数据。每组测试数据的第一行有三个整数N,M,T(2<=N,M<=8,T>0)。接下来N行M列为展馆布置图,其中包括:

'S':入口
'E':出口
'J':放有宝石的区域,至少出现一次
'.':空白区域
'#':墙
 

Output
对每组测试数据,输出至少要封锁的区域数。
 

Sample Input
2 5 5 5 SJJJJ ..##J .JJJJ .J... EJ... 5 5 6 SJJJJ ..##J .JJJJ .J... EJ...
 

Sample Output
0 2

方法:DFS+BFS.
题目要求问最少堵多少个点让他不能完成任务.

因为 地图只有 8*8 ,并且最多只需要堵 4个地方(起点或者终点的四个方向),所以直接暴力枚举0~3个点的堵法,都不能堵的话,就输出4.枚举用DFS搞定。


#include<queue>  
#include<iostream>  
#include<algorithm>  
#define FOR(i,n) for(i=0;i<n;i++)  
  
using namespace std;  
  
char Map[2][10][10];//地图   
char vis[2][10][10];//访问记录   
int sx,sy,n,m,t;  
int dir[][2]={{1,0},{-1,0},{0,1},{0,-1}};//下,上,右,左   
  
struct Node{  
    int x,y,f;//坐标,楼层   
};  
  
bool bfs(){//标准的BFS   
    queue<Node>que;  
    Node no,ne;  
    int i;  
    memset(vis,-1,sizeof(vis));  
    no.x=sx,no.y=sy,no.f=0;  
    que.push(no);  
    vis[0][sx][sy]=0;  
    while(!que.empty()){  
        no=que.front(),que.pop();  
        if(vis[no.f][no.x][no.y]>=t) continue;//算是剪枝吧   
        FOR(i,4){  
            ne.x=no.x+dir[i][0],ne.y=no.y+dir[i][1],ne.f=no.f;  
            if(ne.x<0||ne.y<0||ne.x>=n||ne.y>=m) continue;  
            if(Map[ne.f][ne.x][ne.y]=='#') continue;  
            if(Map[ne.f][ne.x][ne.y]=='J') ne.f=1;  
            if(Map[ne.f][ne.x][ne.y]=='E'&&ne.f) return false;//ne.f=1表示已经拿到J   
            if(vis[ne.f][ne.x][ne.y]!=-1) continue;  
            vis[ne.f][ne.x][ne.y]=vis[no.f][no.x][no.y]+1;  
            que.push(ne);  
        }  
    }  
    return true;  
}  
  
bool DFS(int tot){//标准DFS ,tot表示要堵的点的个数   
    int i,j;  
    if(!tot) return bfs();  
    FOR(i,n)  
    FOR(j,m){  
        if(Map[0][i][j]=='.'||Map[0][i][j]=='J'){  
            char emp=Map[0][i][j];  
            Map[0][i][j]='#';  
            if(DFS(tot-1)) return true;  
            Map[0][i][j]=emp;  
        }  
    }  
    return false;  
}  
  
int main(){  
    int k,i,j,a,b;  
    scanf("%d",&k);  
    while(k--){  
        scanf("%d%d%d",&n,&m,&t);  
        FOR(i,n){  
            scanf("%s",Map[0][i]);  
            FOR(j,m) if(Map[0][i][j]=='S') sx=i,sy=j;  
            strcpy(Map[1][i],Map[0][i]);//复制第二层楼   
        }  
        FOR(i,4)  if(DFS(i)){//把0~3个的点搜索一遍   
            printf("%d\n",i);  
            break;  
        }  
        i==4?puts("4"):0;//如果前三点都没有成立的,最多四个,所以输出四   
    }  
    return 0;  
}













评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值