您的位置:首页 > 大数据 > 人工智能

HDU 1983 Kaitou Kid - The Phantom Thief (2)

2012-08-16 17:21 316 查看
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**************************************************************************************************************************** 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1983 方法:DFS+BFS. 题目要求问最少堵多少个点让他不能完成任务. 因为 地图只有 8*8 ,并且最多只需要堵 4个地方(起点或者终点的四个方向),所以直接暴力枚举0~3个点的堵法,都不能堵的话,就输出4.枚举用DFS搞定。 代码1:

[code]
#include<cstdio>
#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;
}[/code]



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: