暴力
三重循环,枚举学生,障碍和老师,再判断是否合法。
时间复杂度:\(\Theta (mxy)\)。但是会 TLE。
暴力优化
用数组 \(oier\) 来存储二元组 \((x, y)\) 对应的坐标 \(z\)。
这样就省去的开三维数组的成本。
然后只用枚举学生和老师,再判断维度坐标不同数是否为 \(k-1\) 个,以及中间有没有障碍即可。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int maxm = 1003;
vector<int> oier[maxm][maxm]; // oier: 存储 (x, y) 的坐标 z
int n, k, m, x, y;
int oi[maxm][5], bar[maxm][5], tea[maxm][5];
// oi: 学生,bar: 障碍,tea: 老师
int ans[maxm], d[5]; // d: d[1], d[2], d[3] 存储 (x, y, z)
// ans: 答案
// check: 判断中间是否有障碍
bool check() {
int x = d[1], y = d[2], z = d[3];
for (int i = 0; i < oier[x][y].size(); i++) {
if (oier[x][y][i] == z) // 如果 z 坐标相同,说明撞到一起,也就是有障碍
return 1;
}
return 0;
}
int main() {
scanf("%d%d%d%d%d", &n, &k, &m, &x, &y);
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= k; j++)
scanf("%d", &oi[i][j]);
oier[oi[i][1]][oi[i][2]].push_back(oi[i][3]);
}
for (int i = 1; i <= x; i++) {
for (int j = 1; j <= k; j++)
scanf("%d", &bar[i][j]);
oier[bar[i][1]][bar[i][2]].push_back(bar[i][3]);
}
for (int i = 1; i <= y; i++) {
for (int j = 1; j <= k; j++)
scanf("%d", &tea[i][j]);
oier[tea[i][1]][tea[i][2]].push_back(tea[i][3]);
}
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= y; j++) {
int cha = 0, l = 0;
// l: 记录不同的那一个维度是在哪一位
for (int p = 1; p <= k; p++) { // 判断维度不同数量
if (oi[i][p] == tea[j][p])
cha++;
else
l = p;
d[p] = oi[i][p]; // d 存储学生的坐标
}
if (cha != k - 1) continue;
int cnt = 1;
// 因为不存在 2 个坐标相同,所以可以直接比大小,确定从那个开始
int start = max(oi[i][l], tea[j][l]);
int fin = min(oi[i][l], tea[j][l]);
for (int p = fin + 1; p < start; p++) {
d[l] = p; // d[l] 是不同的那一个维度,变为 p 就是在循环看这一位是不是障碍
if (check()) {
cnt = 0;
break;
}
}
ans[j] += cnt; // 答案更新
}
}
for (int i = 1; i <= y; i++)
printf("%d ", ans[i]);
return 0;
}
标签:障碍,int,题解,d%,oier,加训,maxm,include,P11372
From: https://www.cnblogs.com/panda-lyl/p/18608745