Fire Game FZU - 2150

14 篇文章 0 订阅
1 篇文章 0 订阅

这个题题意是两个人在草地上选两点为起点放火,问能不能把草地烧完,能的话画出最短的时间。做法就是选两个起点进行BFS,由于图比较小,可以直接枚举任意两个点进行BFS,选取最短时间

这是一个有两个起点的BFS,起初我是打算开两个队列,然后同时进行BFS,然后错了,,后来一想,即便是把所有的点都放在同一个队列里,也是相当于从两个点开始的BFS,然而还是Wrong,后来想是不是判断不能燃烧所有的草地那个地方错了,本来我是通过一个grass_num记录一共有多少块草地,然后每往队列里压入一个就自减,return的时候判断grass_num是不是为0,后来改成了遍历了。。遍历就过了

//leehaoze
#include <iostream>
#include <deque>
#include <string>
#include <vector>
#include <queue>
#include <cstdio>
#include <stack>
#include <algorithm>
#include <cstring>
#include <cctype>
#include <cstdio>
#include <cmath>
#include <cstdlib>

using namespace std;
const int INF = 1 << 29;
#define INC_SAT(val) (val = ((val)+1 > (val)) ? (val)+1 : (val))
#define ARR_SIZE(a) ( sizeof( (a) ) / sizeof( (a[0]) ) )
#define ULL unsigned long long

#define MAXN (10 + 5)


struct Pos {
    Pos(int x, int y, int step) : x_(x), y_(y), step_(step) {}

    int x_, y_, step_;
};

int Move_X[] = {0, 0, 1, -1};
int Move_Y[] = {1, -1, 0, 0};

int T;
int N, M, grass_num;
char map[MAXN][MAXN];
bool visit[MAXN][MAXN];
vector<Pos> V;

void Input() {
    scanf("%d%d", &N, &M);
    getchar();
    grass_num = 0;
    V.clear();
    for (int i = 0; i < N; ++i) {
        for (int j = 0; j < M; ++j) {
            scanf("%c", &map[i][j]);
            if (map[i][j] == '#') {
                grass_num++;
                V.push_back(Pos(i, j, 0));
            }
            visit[i][j] = false;
        }
        getchar();
    }
}

bool Legal(int dx, int dy) {
    return dx >= 0 && dx < N && dy >= 0 && dy < M && !visit[dx][dy] && map[dx][dy] == '#';
}


int BFS(Pos startA, Pos startB) {
    queue<Pos> Q;
    Q.push(startA);
    Q.push(startB);
    visit[startA.x_][startA.y_] = true;
    visit[startB.x_][startB.y_] = true;
    while (!Q.empty()) {
        Pos now = Q.front();
        Q.pop();
        for (int i = 0; i < 4; ++i) {
            int dx = now.x_ + Move_X[i];
            int dy = now.y_ + Move_Y[i];
            if (Legal(dx, dy)) {
                visit[dx][dy] = true;
                Q.push(Pos(dx, dy, now.step_ + 1));
            }
        }
        if (Q.empty()) {
            return now.step_;
        }
    }
}

bool Judge() {
    for (int i = 0; i < N; ++i) {
        for (int j = 0; j < M; ++j) {
            if (map[i][j] == '#' && !visit[i][j]) {
                return false;
            }
        }
    }
    return true;
}

void Clear_Visit() {
    for (int i = 0; i < N; ++i) {
        for (int j = 0; j < M; ++j) {
            visit[i][j] = false;
        }
    }
}

void Enumerate() {
    int ans = MAXN * MAXN;
    int size = (int) V.size();
    for (int i = 0; i < size; ++i) {
        for (int j = i; j < size; ++j) {
            Clear_Visit();
            int temp = BFS(V[i], V[j]);
            if (Judge()) {
                ans = min(ans, temp);
            }
        }
    }
    if (ans == MAXN * MAXN)
        cout << -1 << endl;
    else
        cout << ans << endl;
}


int main() {
#ifdef LOCAL
    freopen("IN.txt", "r", stdin);
#endif
    std::ios::sync_with_stdio(false);
    scanf("%d", &T);
    getchar();
    for (int i = 0; i < T; ++i) {
        Input();
        cout << "Case " << i + 1 << ": ";
        Enumerate();
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值