http://acm.hdu.edu.cn/showproblem.php?pid=1983
首先,题目要求出口和入口不能封闭,那么,只要把出口或入口的周围全给封闭了那盗贼肯定无法成功偷盗,出口或入口周围最多
会有四个点,所以初始答案ans=4(没必要计算出出口或入口可以封闭的最小值,就初始为4就好),然后从一到四枚举看有没有
最小的符合条件的值,
所以先用BFS查找出至少偷到一个宝石的最小时间的路径,记录下来,然后枚举封闭路径上的点递归回去,再BFS判断是否能偷盗
成功---DFS中插入BFS
code
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
struct point{
int x,y;
int time,flag;//记录时间和是否至少偷到一个宝石
int rx[],ry[];//记录路径
};
char map[][];
int visit[][][];//开三维的数组时因为有偷到了和还没有偷到两种情况,作用相当于是当偷到第一个宝石后,再议这个宝石的地方为起点寻找到终点的时间最短路径,确保了是最短的
int n,m,sx,sy,tt,ans;
int dx[]={,-,,};
int dy[]={,,,-};
void DFS(int deep)
{
int i,k;
if (deep>ans) return ;
memset(visit,,sizeof(visit));
queue<point>Q;
point now,next;
now.x=sx,now.y=sy;
now.time=now.flag=;
visit[now.x][now.y][now.flag]=;
Q.push(now);
int minn=-;
while (!Q.empty())
{
now=Q.front();
Q.pop();
if (map[now.x][now.y]=='E'&&now.flag==)
{
minn=now.time;
break;
}
for (i=;i<;i++)
{
next.x=now.x+dx[i];
next.y=now.y+dy[i];
if (next.x<||next.x>n||next.y<||next.y>m)continue;
if (map[next.x][next.y]=='#')continue;
if (now.time>=tt)continue;
if (map[next.x][next.y]=='J') next.flag=;
else next.flag=now.flag;
if (visit[next.x][next.y][next.flag]==)continue;
for (k=;k<=now.time;k++) //记录路径
{
next.rx[k]=now.rx[k];
next.ry[k]=now.ry[k];
}
next.time=now.time+;
visit[next.x][next.y][next.flag]=;
next.rx[next.time]=next.x;
next.ry[next.time]=next.y;
Q.push(next);
}
}
if (minn==-)
{
if (deep<ans)
ans=deep;
return ;
}
for (i=;i<=now.time;i++)
{
char op=map[now.rx[i]][now.ry[i]];
if (op=='E'||op=='S') continue;
map[now.rx[i]][now.ry[i]]='#';
DFS(deep+);
map[now.rx[i]][now.ry[i]]=op;//回溯
}
}
int main()
{
int t,i,j;
while (~scanf("%d",&t))
{
while (t--)
{
getchar();
scanf("%d %d %d",&n,&m,&tt);
for (i=;i<=n;i++)
{
for (j=;j<=m;j++)
{
scanf(" %c",&map[i][j]);
if (map[i][j]=='S')
sx=i,sy=j;
}
}
ans=;
DFS();
printf("%d\n",ans);
}
}
return ;
}