80分TLE了,加了记忆化搜索(玄关)

P1141 01迷宫

___HatsuneMiku___ @ 2024-07-24 16:43:08

#include <bits/stdc++.h>
using namespace std;
int n, m;
int a[1005][1005];
int vis[1005][1005];
int mem[1005][1005];
class Node
{
public:
    int x, y;
};
int dx[4] = {1, -1, 0, 0};
int dy[4] = {0, 0, 1, -1};
int BFS(int x, int y)
{
    int ans = 1;
    queue<Node> q;
    q.push({x, y});
    vis[x][y] = 1;
    while (!q.empty())
    {
        Node top = q.front();
        q.pop();
        // cout << top.x << ' ' << top.y << '\n';
        for (int i = 0; i < 4; i++)
        {
            int tx = top.x + dx[i];
            int ty = top.y + dy[i];
            if (tx >= 1 && tx <= n && ty >= 1 && ty <= n)
                if (a[tx][ty] != a[top.x][top.y] && !vis[tx][ty])
                {
                    q.push({tx, ty});
                    vis[tx][ty] = 1;
                    ans++;
                }
        }
    }
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            if (vis[i][j])
            {
                vis[i][j] = 0;
                mem[i][j] = ans;
            }
    return ans;
}
void solve(void)
{
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
        {
            char c;
            cin >> c;
            a[i][j] = c - '0';
        }
    for (int i = 1; i <= m; i++)
    {
        int x, y;
        cin >> x >> y;
        if (!mem[x][y])
        {
            int Ans = BFS(x, y);
            cout << Ans << '\n';
        }
        else
            cout << mem[x][y] << '\n';
    }
    return;
}
int main()
{
    // freopen(".in","r",stdin);
    // freopen(".out","w",stdout);
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    solve();

    return 0;
}

by ___HatsuneMiku___ @ 2024-07-24 16:43:58

@wulei0204


by ___HatsuneMiku___ @ 2024-07-24 16:45:07

@LJT_always_AC


by Fishen @ 2024-07-24 16:52:40

SVW嬟嬸侢  } ?  ?伷 佹 塻jh Vj ??孁??t#嬘胳臜 柢?劺uh € j ?P??3缐_^[脨SVWU嬞嬺嬭荂  jh h  U栳?孁

兡鑻鶍羟D3蓧LT塗§臜 ?雓?? 塂?媂;\rR嬅?B ;DwE;\s塡?媓?h桦??$咑t? tN腌伳  ^[脥@


by Fishen @ 2024-07-24 16:53:15

??婡 C?


by ZYLZPP @ 2024-07-24 16:53:20

@LUO_Never_AC

你每次BFS是 n^2 的,一共有 10^5 个询问,最多 10^{11}

可以考虑每次BFS遍历到的所有点的答案与询问点的答案相同,下次都不用再BFS了


by ZYLZPP @ 2024-07-24 16:54:29

@Fishen

乱码?


by ___HatsuneMiku___ @ 2024-07-24 17:06:12

@ZYLZPP 但是我加了呀

    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            if (vis[i][j])
            {
                vis[i][j] = 0;
                mem[i][j] = ans;
            }

这一段就是枚举所有访问过的点,给这些点打上标记(记忆化)


by ___HatsuneMiku___ @ 2024-07-24 17:09:27

@LUO_Never_AC 更新代码(结果函数两个TLE):

#include <bits/stdc++.h>
using namespace std;
int n, m;
int a[1005][1005];
int vis[1005][1005];
int mem[1005][1005];
class Node
{
public:
    int x, y;
};
int dx[4] = {1, -1, 0, 0};
int dy[4] = {0, 0, 1, -1};
int BFS(int x, int y)
{
    int ans = 1;
    queue<Node> q;
    q.push({x, y});
    vis[x][y] = 1;
    while (!q.empty())
    {
        Node top = q.front();
        q.pop();
        // cout << top.x << ' ' << top.y << '\n';
        if (mem[top.x][top.y])
        {
            ans += mem[top.x][top.y];
            break;
        }
        for (int i = 0; i < 4; i++)
        {
            int tx = top.x + dx[i];
            int ty = top.y + dy[i];
            if (tx >= 1 && tx <= n && ty >= 1 && ty <= n)
                if (a[tx][ty] != a[top.x][top.y] && !vis[tx][ty])
                {
                    q.push({tx, ty});
                    vis[tx][ty] = 1;
                    ans++;
                }
        }
    }
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            if (vis[i][j])
            {
                vis[i][j] = 0;
                mem[i][j] = ans;
            }
    return ans;
}
void solve(void)
{
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
        {
            char c;
            cin >> c;
            a[i][j] = c - '0';
        }
    for (int i = 1; i <= m; i++)
    {
        int x, y;
        cin >> x >> y;
        if (!mem[x][y])
        {
            int Ans = BFS(x, y);
            cout << Ans << '\n';
        }
        else
            cout << mem[x][y] << '\n';
    }
    return;
}
int main()
{
    // freopen(".in","r",stdin);
    // freopen(".out","w",stdout);
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    solve();

    return 0;
}

by ___HatsuneMiku___ @ 2024-07-24 17:10:04

@LUO_Never_AC @ZYLZPP

#include <bits/stdc++.h>
using namespace std;
int n, m;
int a[1005][1005];
int vis[1005][1005];
int mem[1005][1005];
class Node
{
public:
    int x, y;
};
int dx[4] = {1, -1, 0, 0};
int dy[4] = {0, 0, 1, -1};
int BFS(int x, int y)
{
    int ans = 1;
    queue<Node> q;
    q.push({x, y});
    vis[x][y] = 1;
    while (!q.empty())
    {
        Node top = q.front();
        q.pop();
        // cout << top.x << ' ' << top.y << '\n';
        if (mem[top.x][top.y])
        {
            ans += mem[top.x][top.y];
            break;
        }
        for (int i = 0; i < 4; i++)
        {
            int tx = top.x + dx[i];
            int ty = top.y + dy[i];
            if (tx >= 1 && tx <= n && ty >= 1 && ty <= n)
                if (a[tx][ty] != a[top.x][top.y] && !vis[tx][ty])
                {
                    q.push({tx, ty});
                    vis[tx][ty] = 1;
                    ans++;
                }
        }
    }
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            if (vis[i][j])
            {
                vis[i][j] = 0;
                mem[i][j] = ans;
            }
    return ans;
}
void solve(void)
{
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
        {
            char c;
            cin >> c;
            a[i][j] = c - '0';
        }
    for (int i = 1; i <= m; i++)
    {
        int x, y;
        cin >> x >> y;
        if (!mem[x][y])
        {
            int Ans = BFS(x, y);
            cout << Ans << '\n';
        }
        else
            cout << mem[x][y] << '\n';
    }
    return;
}
int main()
{
    // freopen(".in","r",stdin);
    // freopen(".out","w",stdout);
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    solve();

    return 0;
}

by ZYLZPP @ 2024-07-24 17:11:54

@LUO_Never_AC

你这样每个连通块都是 n^2 复杂度

遍历了没有vis的非块内点

应该把块内的点记录下来再改

这样每个点就只会被他所属的块遍历一遍了


| 下一页