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。dfs搜索要封锁的区域个数,bfs搜索Kid能否盗取宝石。很容易知道封锁的区域最多有4个,因为给入口或者出口围住最多只要4个区域,那么就可以给最大值设成4,然后去搜。
#include<cstdio> #include<cstring> #include<queue> using namespace std; struct p { int x,y,t,su; int s1[90],s2[90]; }; int n,m,sx,sy,ans,time; char map[10][10]; int v[10][10][2]; int yi[4][2]={{1,0},{0,1},{-1,0},{0,-1}}; void dfs(int k) { queue<p>q; p f,r; int vis=-1,i,j; if (k>ans) return ; f.x=sx; f.y=sy; f.t=0; f.su=0; memset(v,0,sizeof(v)); while (!q.empty()) q.pop(); v[sx][sy][0]=1; q.push(f); while (!q.empty()) { r=q.front(); q.pop(); if (r.t>time) continue; if (map[r.x][r.y]==‘E‘&&r.su) {vis=r.t;break;} f.t=r.t+1; f.su=r.su; for (i=0;i<4;i++) { f.x=r.x+yi[i][0]; f.y=r.y+yi[i][1]; if (f.x>=0&&f.x<n&&f.y>=0&&f.y<m&&map[f.x][f.y]!=‘#‘) { if (map[f.x][f.y]==‘J‘) f.su=1; else f.su=r.su; if (v[f.x][f.y][f.su]) continue; v[f.x][f.y][f.su]=1; for (j=1;j<=r.t;j++) { f.s1[j]=r.s1[j]; f.s2[j]=r.s2[j]; } f.s1[f.t]=f.x; f.s2[f.t]=f.y; q.push(f); } } } if (vis==-1) { if (ans>k) ans=k; return ; } for (i=1;i<=r.t;i++) { char c=map[r.s1[i]][r.s2[i]]; if (c==‘S‘||c==‘E‘) continue; map[r.s1[i]][r.s2[i]]=‘#‘; dfs(k+1); map[r.s1[i]][r.s2[i]]=c; } } int main() { int c,i,j; scanf("%d",&c); while (c--) { scanf("%d%d%d",&n,&m,&time); for(i=0;i<n;i++) for(j=0;j<m;j++) { scanf(" %c",&map[i][j]); if (map[i][j]==‘S‘) {sx=i;sy=j;} } ans=4; dfs(0); printf("%d\n",ans); } return 0; }
时间: 2024-10-22 03:21:18