求助!传统BFS会TLE!求大佬指点如何简化!

P2895 [USACO08FEB] Meteor Shower S

qzybkjdx0605 @ 2020-07-28 19:54:48


#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
using namespace std;
#define M 305

int n, map[M][M], ans = 0x7fffffff;
bool vis[M][M];
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};

int bfs(int xx, int yy, int tt)
{
    if (map[xx][yy] == -1)
    {
        ans = min(tt, ans);
        return ans;
    }
    for (int i = 0; i < 4; i++)
    {
        int nx = xx + dx[i], ny = yy + dy[i];
        if (nx >= 0 && ny >= 0 && !vis[nx][ny] && (map[nx][ny] > tt + 1 || map[nx][ny] == -1))
        {
            //vis[nx][ny] = true; 添加这行能解决tle问题但是会wa一半的样例
            bfs(nx, ny, tt + 1);
        }
    }
}

int main()
{
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    cin >> n;
    int sx, sy, st;
    for (int i = 0; i < 305; i++)
        for (int j = 0; j < 305; j++)
            map[i][j] = -1;
    for (int i = 1; i <= n; i++)
    {
        cin >> sx >> sy >> st;
        if (st <= map[sx][sy] || map[sx][sy] == -1)
            map[sx][sy] = st;
        for (int k = 0; k < 4; k++)
        {
            if (sx + dx[k] >= 0 && sy + dy[k] >= 0)
                if (st <= map[sx + dx[k]][sy + dy[k]] || map[sx + dx[k]][sy + dy[k]] == -1)
                    map[sx + dx[k]][sy + dy[k]] = st;
        }
    }
    vis[0][0] = true;
    bfs(0, 0, 0);
    if (ans != 0x7fffffff)
        cout << ans << endl;
    else
        cout << "-1" << endl;
    return 0;
}```

by Wu_Ren @ 2020-07-28 20:07:39

这不是个带剪枝的搜索吗,还传统bfs,如果遍历了相同的点复杂度都不对了


by Wu_Ren @ 2020-07-28 20:12:38

@Wu_Ren 加上vis才是正解的bfs,至于为什么wa了还要再看看


by 天命之路 @ 2020-07-28 20:13:28

bfs? 不是dfs?


by 天命之路 @ 2020-07-28 20:14:20

vis[nx][ny]=true;
bfs(nx,ny,tt+1);
vis[nx][ny]=false;

by 天命之路 @ 2020-07-28 20:14:37

@qzybkjdx0605 试试能不能行


by Wu_Ren @ 2020-07-28 20:18:05

@Wu_Ren 噢,我懂为什么wa了

比如有一个2*2 的图,你开始在(0,0)点,其中 (1,0) 是安全的,其他点都是危险的

在你的递归中,你先走到 (0,1) 再到 (1,1) 再回到 (1,0),此时这三个点的 vis 都是 true 了,也就是说你不会再走这三个点了,但此时你找到的答案是3

应该向传统的bfs一样,把新扩展的点放在队列后面,每次从队列最前面的点开始扩展,这样才能保证扩展出来的点答案最优


|