【題目鏈接】
【思路要點】
- 考慮 的情況,我們需要判斷是否存在相鄰的黑色像素。
- 如果我們知道兩個黑色像素的相對方向,則可以採取如下策略:
- 不妨令兩個黑色像素在同一列,計算每一行的 ,並計算得到的數組的前綴 與後綴 ,記爲 。若存在一個 使得 爲 ,則說明兩個黑色像素所在的行相距至少爲 ,從而可以判斷它們是否相鄰。
- 在不知道兩個黑色像素的相對方向時,可以採取如下策略:
- 若將座標系進行旋轉 ,則可以將兩個點 的曼哈頓距離 轉化爲切比雪夫距離 ,從而在兩維座標上都進行上文的判斷即可。
- 注意到上面的過程本質上判斷了兩個黑色像素的距離是否 ,那麼再判斷一下兩個黑色像素的距離是否 就行了。
- 令 同階,時間複雜度 ,使用操作次數 ,涉及元素個數 。
- 以下代碼沒有考慮一些可能的對操作次數的常數優化。
【代碼】
#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); }