(有注释) dfs 80pts TLE 求调
查看原帖
(有注释) dfs 80pts TLE 求调
970949
CleverSea楼主2024/10/5 23:39

这个题两个没过的测试点均为TLE,求大佬帮忙优化一下时间复杂度,感谢!

原题链接:戳我
评测数据:戳我
源代码:

#include <bits/stdc++.h>
#define int long long
using namespace std;

const int N = 1010;

int T;
int n, h, r;
int dx[N], dy[N], dz[N]; // dx[i]、dy[i]、dz[i]分别表示第i个洞的x、y、z坐标

// f[i][j]表示i洞和j洞是否相切/相交,fs[i]、fx[i]分别表示i洞是否与上表面、下表面相切/相交,rec[i]表示i洞能否到达上表面,zg[i]表示这个洞是否走过,flag表示当前有没有dfs到上表面
bool f[N][N], fs[N], fx[N], rec[N], flag, zg[N];

double cal(int x, int y) // 计算x洞与y洞之间的距离
{
    return 1.0 * sqrt((dx[x] - dx[y]) * (dx[x] - dx[y]) + (dy[x] - dy[y]) * (dy[x] - dy[y]) + (dz[x] - dz[y]) * (dz[x] - dz[y]));
}

void dfs(int p)
{
    // 如果记忆化数组已经标记过该洞可以到达上表面,就标记,然后直接return掉
    if (rec[p])
    {
        flag = 1;
        return;
    }

    // 如果已经找到到达上表面的路,就不找了
    if (flag) return;

    // 如果该球与上表面相切/相交,则说明找到了
    if (fs[p])
    {
        flag = 1;
        return;
    }

    // 没找到的话,继续dfs下一层
    for (int i = 1; i <= n; i++)
    {
        if (zg[i] == 0 && i != p && f[i][p] == 1) // 如果 这个洞没去过 且 这个洞不是本身 且 这个洞可以到达 则dfs到这个洞
        {
            zg[i] = 1; // 标记这个洞去过了
            dfs(i);
            zg[i] = 0; // 回溯
        }
    }
}

signed main()
{
    ios::sync_with_stdio(0); // 读写加速
    cin >> T;
    while (T--)
    {
        // 初始化rec、f、fs、fx、flag
        memset(rec, 0, sizeof(rec));
        memset(f, 0, sizeof(f));
        memset(fs, 0, sizeof(fs));
        memset(fx, 0, sizeof(fx));
        flag = 0;

        // 输入
        cin >> n >> h >> r;
        for (int i = 1; i <= n; i++) cin >> dx[i] >> dy[i] >> dz[i];

        // 逐个判断该洞是否与上/下表面相切/相交
        for (int i = 1; i <= n; i++)
        {
            if (dz[i] + r >= h) fs[i] = 1;
            if (dz[i] - r <= 0) fx[i] = 1;
        }

        // 判断任意两个洞之间是否相切/相交
        for (int i = 1; i <= n; i++)
        {
            for (int j = i + 1; j <= n; j++)
            {
                if (cal(i, j) - 2 * r <= 0) f[i][j] = f[j][i] = 1;
            }
        }

        // 对于每一个与下表面相交/相切的洞,以它为起点开始dfs
        for (int i = 1; i <= n; i++)
        {
            if (fx[i] == 1)
            {
                zg[i] = 1; // 标记该洞走过了
                dfs(i);
                zg[i] = 0; // 回溯
            }
        }

        // 输出结果
        if (flag) cout << "Yes" << endl;
        else cout << "No" << endl;
    }

    // 这行代码永远不会被执行,不用管它
    if (3 - 1 != 2) cout << "114514" << endl;

    // 优雅地结束
    return 0;
}

2024/10/5 23:39
加载中...