【题目大意】:你得知Kid将会在展览开始后T分钟内盗取至少一颗宝石,并离开展馆。整个展馆呈矩形分布,划分为N*M个区域,有唯一的入口和出口(不能从出口进入,同样不能从入口出去)。由某个区域可直接移动至相邻四个区域中的一个,且最快需要一分钟。假设Kid进入放有宝石的区域即可盗取宝石,无需耗时。问至少要封锁几个区域(可以封锁放有宝石的区域,但不能封锁入口和出口)才能保证Kid无法完成任务。
【解题思路】:其实读完题目我们显然可以发现,在最坏的情况下我只需要将出口和入口附近非“#”的区域封闭即刻。换句话说,最坏的情况不会超过封锁4块区域。
因此,我们不妨考虑先根据出入口和在不封锁区域的情况下是否存在可行路径来得到当前所需封锁区域的最小值。
之后,我们通过dfs来枚举小于当前最小区域封锁值时的点,再通过bfs求最短路验证即刻。
坑爹的事...下午贡献了无限次wa。。。现实把p.x敲成p,x之后发现去min的时候居然忘了写min函数....==....真应该剖腹以谢天下!!!
【代码】:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <cmath>
#include <string>
#include <cctype>
#include <map>
#include <iomanip>
using namespace std;
#define eps 1e-8
#define pi acos(-1.0)
#define inf 1<<30
#define pb push_back
#define lc(x) (x << 1)
#define rc(x) (x << 1 | 1)
#define lowbit(x) (x & (-x))
#define ll long long
int tx[4]={-1,1,0,0};
int ty[4]={0,0,-1,1};
int x,y,minn,t,xx,yy,n,m;
int vis[10][10][2];
char ch[10][10];
bool flag1;
char tmp[5];
struct Node{
int x,y,cnt,flag;
Node() {}
Node(int a,int b,int c,int d){
x=a,y=b,cnt=c,flag=d;
}
};
bool check(int x,int y){
if (x>=0 && x<n && y>=0 && y<m) return true;
else return false;
}
bool solve_bfs(){
queue<Node> que;
que.push(Node(x,y,0,0));
memset(vis,0,sizeof(vis));
vis[x][y][0]=1;
while (!que.empty()){
Node q;
q=que.front();
que.pop();
for (int i=0; i<4; i++){
Node p;
p.x=q.x+tx[i];
p.y=q.y+ty[i];
p.cnt=q.cnt+1;
p.flag=q.flag;
if (check(p.x,p.y) && ch[p.x][p.y]!='#'){
if (ch[p.x][p.y]=='E' && p.flag==1) return true;
if (ch[p.x][p.y]=='J') p.flag=1;
if (p.cnt<t && vis[p.x][p.y][p.flag]==0){
vis[p.x][p.y][p.flag]=1;
que.push(p);
}
}
}
}
return false;
}
int solve_min(){
int nx,ny,min1=0,min2=0;
for (int i=0; i<4; i++){
nx=x+tx[i];
ny=y+ty[i];
if (check(nx,ny) && (ch[nx][ny]=='.' || ch[nx][ny]=='J'))
min1++;
}
for (int i=0; i<4; i++){
nx=xx+tx[i];
ny=yy+ty[i];
if (check(nx,ny) && (ch[nx][ny]=='.' || ch[nx][ny]=='J'))
min2++;
}
return min(min1,min2);
}
void solve_dfs(int count,int now){
if (count<minn){
for (int i=0; i<n; i++)
for (int j=0; j<m; j++){
if (ch[i][j]=='.' || ch[i][j]=='J'){
tmp[now]=ch[i][j];
ch[i][j]='#';
if (now==count) if (!solve_bfs()) {minn=min(count,minn); flag1=true; return ;}
if (flag1) return ;
if (now<count) solve_dfs(count,now+1);
ch[i][j]=tmp[now];
}
}
}
else return ;
}
int main() {
int T;
scanf("%d",&T);
while (T--){
scanf("%d%d%d",&n,&m,&t);
getchar();
for (int i=0; i<n; i++){
for (int j=0; j<m; j++){
scanf("%c",&ch[i][j]);
if (ch[i][j]=='S') x=i,y=j;
if (ch[i][j]=='E') xx=i,yy=j;
}
getchar();
}
minn=solve_min();
if (!solve_bfs()) minn=0;
flag1=false;
solve_dfs(1,1);
flag1=false;
solve_dfs(2,1);
flag1=false;
solve_dfs(3,1);
printf("%d\n",minn);
}
return 0;
}