题目通道
解题思路
先暴力取两个点,这里的n和m的上限都很小,不会炸。接着双起点bfs,把草烧到无法再烧的程度( 全部草烧着了,或许有些草无法被点燃 )。此时已经点燃的草vis的值是1。记录烧的最大时间 temp。再判断,草坪上的草是不是全部烧着了,状态(是草,是烧着了,对应的变量是 grid[i][j] == ‘#’ 和 vis[i][j] == 1 )。如果全部草烧着了, ans=min(ans,temp);
展示自己bfs的写法
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <queue>
#include <vector>
using namespace std;
#define inf 0x3f3f3f3f
int n,m;
bool vis[15][15];
char grid[15][15];
int casee=0;
int ans=inf;
struct node
{
int x,y,depth;
};
vector <node>grass;
bool check (int x,int y)
{
if (!vis[x][y]&&grid[x][y]=='#'&&x>=0&&x<n&&y>=0&&y<m)
return true;
else
return false;
}
bool judge ()
{
for (int i=0;i<n;++i){
for (int j=0;j<m;++j){
if (grid[i][j]=='#'&&!vis[i][j])
return false;
}
}
return true;
}
void init()
{
grass.clear();
memset(vis,false,sizeof vis);
}
int nex[][2]={-1,0,1,0,0,-1,0,1};
int bfs (node n1,node n2)
{
queue <node> q;
while (!q.empty()) q.pop();
q.push(n1);
q.push(n2);
memset(vis,false,sizeof vis);
vis[n1.x][n1.y] = true;
vis[n2.x][n2.y] = true;
int depthest=0;
while (!q.empty())
{
node now=q.front();
node nxt;
q.pop();
depthest=now.depth;
for (int i = 0; i < 4; i++){
nxt.x = now.x + nex[i][0];
nxt.y = now.y + nex[i][1];
nxt.depth = now.depth + 1;
if ( check(nxt.x,nxt.y) ){
if ( vis[nxt.x][nxt.y] == 0 ){
vis[nxt.x][nxt.y] = 1;
q.push(nxt);
}
}
}
}
return depthest;
}
int main()
{
//freopen("de.txt","r",stdin);
int t;
scanf("%d",&t);
while (t--)
{
init();
ans=inf;
scanf("%d%d",&n,&m);
for (int i=0;i<n;++i)
scanf("%s",grid[i]);
for (int i=0;i<n;++i){
for (int j=0;j<m;++j){
if (grid[i][j]=='#'){
node g;
g.x=i;
g.y=j;
g.depth=0;
grass.push_back(g);
}
}
}
for (int i=0;i<grass.size();++i)
{
for (int j=i;j<grass.size();++j)
{
grass[i].depth=0;
grass[j].depth=0;
int temp=bfs(grass[i],grass[j]);
if (judge())
ans=min(ans,temp);
}
}
printf("Case %d: ",++casee);
if (ans==inf)
printf("-1\n");
else
printf("%d\n",ans);
}
return 0;
}
助记
先处理,queue < node > q;
初始化:1、排空。2、头结点入队。
再处理,防止重复入队的vis
初始化:1、memset(vis,0,sizeof(vis))。2、入队的头结点标记。
更新状态,判断是否合法(坐标的合法性,题目意义的合法性,不能重复入队),再决定是否入队。
某大牛代码
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <queue>
#include <vector>
using namespace std;
#define inf 0x3f3f3f3f
int n,m;
bool vis[15][15];
char grid[15][15];
int casee=0;
int ans=inf;
struct node
{
int x,y,depth;
};
vector <node>grass;
bool check (int x,int y)
{
if (!vis[x][y]&&grid[x][y]=='#'&&x>=0&&x<n&&y>=0&&y<m)
return true;
else
return false;
}
bool judge ()
{
for (int i=0;i<n;++i){
for (int j=0;j<m;++j){
if (grid[i][j]=='#'&&!vis[i][j])
return false;
}
}
return true;
}
void init()
{
grass.clear();
memset(vis,false,sizeof vis);
}
int bfs (node n1,node n2)
{
queue <node> q;
memset(vis,false,sizeof vis);
while (!q.empty()) q.pop();
q.push(n1);
q.push(n2);
int depthest=0;
while (!q.empty())
{
node now=q.front();
q.pop();
if (vis[now.x][now.y])
continue;
vis[now.x][now.y]=true;
depthest=now.depth;
if (check(now.x-1,now.y))
{
node nxt=now;
nxt.x--;
nxt.depth++;
q.push(nxt);
}
if (check(now.x+1,now.y))
{
node nxt=now;
nxt.x++;
nxt.depth++;
q.push(nxt);
}
if (check(now.x,now.y-1))
{
node nxt=now;
nxt.y--;
nxt.depth++;
q.push(nxt);
}
if (check(now.x,now.y+1))
{
node nxt=now;
nxt.y++;
nxt.depth++;
q.push(nxt);
}
}
return depthest;
}
int main()
{
//freopen("de.txt","r",stdin);
int t;
scanf("%d",&t);
while (t--)
{
init();
ans=inf;
scanf("%d%d",&n,&m);
for (int i=0;i<n;++i)
scanf("%s",grid[i]);
for (int i=0;i<n;++i){
for (int j=0;j<m;++j){
if (grid[i][j]=='#'){
node g;
g.x=i;
g.y=j;
g.depth=0;
grass.push_back(g);
}
}
}
for (int i=0;i<grass.size();++i)
{
for (int j=i;j<grass.size();++j)
{
grass[i].depth=0;
grass[j].depth=0;
int temp=min(bfs(grass[i],grass[j]),ans);
if (judge())
ans=min(ans,temp);
}
}
printf("Case %d: ",++casee);
if (ans==inf)
printf("-1\n");
else
printf("%d\n",ans);
}
return 0;
}
可以借鉴的优点
vis判断的地方写法很新。避免 vis下标不合法的情况。