这个题两个没过的测试点均为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;
}