【题目链接】
【思路要点】
- 考虑 的情况,我们需要判断是否存在相邻的黑色像素。
- 如果我们知道两个黑色像素的相对方向,则可以采取如下策略:
- 不妨令两个黑色像素在同一列,计算每一行的 ,并计算得到的数组的前缀 与后缀 ,记为 。若存在一个 使得 为 ,则说明两个黑色像素所在的行相距至少为 ,从而可以判断它们是否相邻。
- 在不知道两个黑色像素的相对方向时,可以采取如下策略:
- 若将坐标系进行旋转 ,则可以将两个点 的曼哈顿距离 转化为切比雪夫距离 ,从而在两维坐标上都进行上文的判断即可。
- 注意到上面的过程本质上判断了两个黑色像素的距离是否 ,那么再判断一下两个黑色像素的距离是否 就行了。
- 令 同阶,时间复杂度 ,使用操作次数 ,涉及元素个数 。
- 以下代码没有考虑一些可能的对操作次数的常数优化。
【代码】
#include "vision.h" #include<bits/stdc++.h> using namespace std; const int MAXN = 405; int num[MAXN][MAXN], tot; int pre[MAXN], suf[MAXN]; int getbool(int n, int m, int k) { for (int i = 2; i <= n + m; i++) { vector <int> opt; opt.clear(); for (int j = 1; j <= n; j++) { int k = i - j; if (k >= 1 && k <= m) opt.push_back(num[j][k]); } if (i != 2) opt.push_back(pre[i - 1]); pre[i] = add_or(opt); } for (int i = n + m; i >= 2; i--) { vector <int> opt; opt.clear(); for (int j = 1; j <= n; j++) { int k = i - j; if (k >= 1 && k <= m) opt.push_back(num[j][k]); } if (i != n + m) opt.push_back(suf[i + 1]); suf[i] = add_or(opt); } vector <int> opt; opt.clear(); for (int i = 2, j = i + k; j <= n + m; i++, j++) { vector <int> tmp; tmp.clear(); tmp.push_back(pre[i]), tmp.push_back(suf[j]); opt.push_back(add_and(tmp)); } int resa = add_or(opt); for (int i = 1; i <= n; i++) for (int j = 1, k = m; j <= k; j++, k--) swap(num[i][j], num[i][k]); for (int i = 2; i <= n + m; i++) { vector <int> opt; opt.clear(); for (int j = 1; j <= n; j++) { int k = i - j; if (k >= 1 && k <= m) opt.push_back(num[j][k]); } if (i != 2) opt.push_back(pre[i - 1]); pre[i] = add_or(opt); } for (int i = n + m; i >= 2; i--) { vector <int> opt; opt.clear(); for (int j = 1; j <= n; j++) { int k = i - j; if (k >= 1 && k <= m) opt.push_back(num[j][k]); } if (i != n + m) opt.push_back(suf[i + 1]); suf[i] = add_or(opt); } opt.clear(); for (int i = 2, j = i + k; j <= n + m; i++, j++) { vector <int> tmp; tmp.clear(); tmp.push_back(pre[i]), tmp.push_back(suf[j]); opt.push_back(add_and(tmp)); } int resb = add_or(opt); for (int i = 1; i <= n; i++) for (int j = 1, k = m; j <= k; j++, k--) swap(num[i][j], num[i][k]); opt.clear(); opt.push_back(resa), opt.push_back(resb); return add_or(opt); } void construct_network(int n, int m, int k) { for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) num[i][j] = tot++; if (k == n + m - 2) { getbool(n, m, k); return; } int greater = getbool(n, m, k + 1); int geq = getbool(n, m, k); int ngr = add_not(greater); vector <int> opt; opt.clear(); opt.push_back(geq), opt.push_back(ngr); add_and(opt); }
来源:https://blog.csdn.net/qq_39972971/article/details/99547267