题目链接:http://acm.fzu.edu.cn/problem.php?pid=2150
题目大意:
就是给你一个字符型矩阵,"#"代表有草,"."代表是石头,一次可以放两把火,但是火必须放在草上,问放火的正确姿势的最短时间,如果不能烧完所有的草,就输出-1.
具体思路:
首先,记录所有的草的位置存入结构体中,然后使用bfs进行遍历,遍历的时候需要从两个点开始,然后跑到队列为空结束,输出最后一个数据对应的步数。为什么是输出最后一步的步数,我觉得原因如下:因为并不知道什么时候整个图上的草是否被烧干净,如果每走一步都判断一下是否烧干净的话肯定会超时,最快的时候是两个火相隔比较远并且能充分利用时间,也就是判断最大连通分量。
代码如下:
#include<iostream>
#include<cstring>
#include<queue>
char a[20][20];
int visited[105][105];
int dis;
int n,m;
using namespace std;
# define INF 0x3f3f3f3f
int f[4][2]= {{1,0},{-1,0},{0,1},{0,-1}};
struct node
{
int xi;
int yi;
int step;
node() {}
node(int s1,int s2,int s3)
{
xi=s1;
yi=s2;
step=s3;
}
} q[10000];
void init()
{
memset(visited,0,sizeof(visited));
}
bool Judge1(int t1,int t2)
{
if(t1>=0&&t1<n&&t2>=0&&t2<m&&visited[t1][t2]==0&&a[t1][t2]=='#')
{
return true;
}
return false;
}
bool Judge2()
{
for(int i=0; i<n; i++)
{
for(int j=0; j<m; j++)
{
if(visited[i][j]==0&&a[i][j]=='#')
return false;
}
}
return true;
}
int bfs(node q1,node q2)
{
queue<node>q;
while(!q.empty())q.pop();
q.push(q1);
q.push(q2);
while(!q.empty())
{
node tempnode=q.front();
q.pop();
if(visited[tempnode.xi][tempnode.yi]==1)
dis=tempnode.step;
int xi=tempnode.xi;
int yi=tempnode.yi;
visited[xi][yi]=1;//注意一定要标记自身,我一开始爆栈就是因为是这个
for(int i=0; i<4; i++)
{
int x=xi+f[i][0];
int y=yi+f[i][1];
if(Judge1(x,y))
{
visited[x][y]=1;
q.push(node(x,y,tempnode.step+1));
}
}
}
return dis;
}
int main()
{
int t;
cin>>t; int s=1;
while(t--)
{
cin>>n>>m;
int num=1;
for(int i=0; i<n; i++)
{
for(int j=0; j<m; j++)
{
cin>>a[i][j];
if(a[i][j]=='#')
{
q[num].xi=i;
q[num].yi=j;
q[num].step=0;
num++;
}
}
}
int ans=INF;
for(int i=1; i<num; i++)
{
for(int j=i; j<num; j++)
{
init();
dis=0;
int temp=bfs(q[i],q[j]);
if(Judge2())
{
ans=min(ans,temp);
}
}
}
cout<<"Case "<<s++<<": ";
if(ans==INF)
cout<<-1<<endl;
else
cout<<ans<<endl;
}
return 0;
}