FZU2150(双起点bfs->多起点)

题目大意:
给出一个height*width的图,'#'表示草坪,'.'表示空地,然后可以选择在任意的两个草坪格子点火,火每 1 s会向周围四个格子扩散,问选择那两个点使得燃烧所有的草坪花费时间最小?
大致思路:
重点是和单起点bfs差不多,唯一不同的就是在刚开始入队的时候将两个起点都入队。可以说是对两个不同根节点的树进行搜索吧(两棵树根节点可相同可不同,枝叶可交叉可不交叉),主要思路就是这个样子喽,剩下的细节就看个人怎么处理了。同样也可以类比到多起点的搜索。而且如果单纯的暴力枚举的话会计算大量的重复所以可以增加一个dat数组讲草的位置保存下来,进行一些优化。(本人对图的建坐标方式可能恰好相反,见谅!)。

这是我的代码运行结果(前一次写的TLE了(小声图片说明

#include <bits/stdc++.h>
using namespace std;
int x,y;
const int MAX = 15;
int dir[][2] = {{-1,0},{0,-1},{1,0},{0,1}};
char vis[MAX][MAX],cur[MAX][MAX]; 
int path[MAX][MAX];     //这个二维数组记录对草对两个起点的最大距离(也就是火烧到此处的时间
struct node{
    int x,y;
    node(int xx=0,int yy=0):
        x(xx),y(yy){}
};
#define check(dx,dy) (0<=dx && dx<x && 0<=dy && dy<y)
vector dat;   //这个保存草的位置
int bfs(node fir,node sec)
{
    memset(path,0,sizeof path);
    memcpy(cur,vis,sizeof vis);
    queue que;
    que.push(fir),que.push(sec);   //两个结点同时入队
    cur[fir.y][fir.x] = '.';cur[sec.y][sec.x] = '.';
    while (!que.empty())
    {
        node tmp = que.front(); que.pop();
        for (int i=0;i<4;i++)
        {
            int dx = tmp.x+dir[i][0],dy = tmp.y+dir[i][1];
            if (check(dx,dy) && '#'==cur[dy][dx])
            {
                que.push(node(dx,dy));
                path[dy][dx] = path[tmp.y][tmp.x] + 1;
                cur[dy][dx] = '.';
            }
        }        
    }
    int res = -0x3f3f3f3f;
    for (int i=0;i<y;i++)
        for (int j=0;j<x;j++)
        {
            if (path[i][j]>res)
                res = path[i][j];
            if ('#'==cur[i][j])
                return -1;   //如果发现草没有烧完,就返回-1,否则返回时间
        }
    return res;
}
int main()
{
    int t;
    while (cin >> t){
        int count = 0;
        while (t--){
            cin >> y >> x;
            dat.clear();
            for (int i=0;i<y;i++)
            {
                scanf("%s",vis[i]);
                for (int j=0;j<x;j++)
                    if ('#'==vis[i][j])
                        dat.push_back(node(j,i));
            }
            int ans = 0x3f3f3f3f;  //枚举
            for (int i=0;i<dat.size();i++)
                for (int j=i;j<dat.size();j++)
                {
                    int tmp = bfs(dat[i],dat[j]);
                    if (-1==tmp)
                        continue;
                    if (tmp<ans)
                        ans = tmp;
                }
            if (0x3f3f3f3f==ans)
                ans = -1;
            cout << "Case " << ++count << ": " << ans << endl;
        }
    }
    return 0;
}
全部评论

相关推荐

想要成为offer实力者:亚信实习能干这些?确定不是包装
点赞 评论 收藏
分享
09-25 10:34
东北大学 Java
多面手的小八想要自然醒:所以读这么多年到头来成为时代车轮底下的一粒尘
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务