【BFS 重构树】P11907 [NHSPC 2023] F. 恐怖的黑色魔物|省选-
本文涉及知识点
C++并集查找 重构树
C++BFS算法
P11907 [NHSPC 2023] F. 恐怖的黑色魔物
题目描述
G 公司最近用黑科技在某个神秘的地方建立了新的研发中心。这座研发中心的形状是长方体,内部共有 FFF 层楼,每一层楼均有由 MMM 列 NNN 行组成的矩形房间。一个房间的位置用三个正整数 (p,q,r)(p, q, r)(p,q,r) 表示,代表该房间位于研发中心 ppp 楼的第 qqq 列第 rrr 行。
G 公司的员工均可以通过黑科技直接传送到隔壁、楼下或楼上的房间。更明确地说,位于房间 (p,q,r)(p, q, r)(p,q,r) 的 G 公司员工,
- 当 p>1p > 1p>1 时,可以传送到房间 (p−1,q,r)(p-1, q, r)(p−1,q,r)。
- 当 p<Fp < Fp<F 时,可以传送到房间 (p+1,q,r)(p+1, q, r)(p+1,q,r)。
- 当 q>1q > 1q>1 时,可以传送到房间 (p,q−1,r)(p, q-1, r)(p,q−1,r)。
- 当 q<Mq < Mq<M 时,可以传送到房间 (p,q+1,r)(p, q+1, r)(p,q+1,r)。
- 当 r>1r > 1r>1 时,可以传送到房间 (p,q,r−1)(p, q, r-1)(p,q,r−1)。
- 当 r<Nr < Nr<N 时,可以传送到房间 (p,q,r+1)(p, q, r+1)(p,q,r+1)。
G 公司为了节省员工的用餐休息时间,在其中的 RRR 个房间开设了餐厅,方便员工在研发中心内直接用餐。但餐厅的食物会滋生一种恐怖的黑色魔物,有一部分的 G 公司员工非常害怕这种恐怖的黑色魔物,因此不敢在这些餐厅用餐。
你的上司 K 先生特别害怕这种恐怖的黑色魔物。他总认为这些恐怖的黑色魔物,也能通过黑科技,在研发中心里自由穿梭。他定义了「黑色恐怖距离」:若一个房间至少须使用 ddd 次黑科技传送,才能抵达餐厅,则该房间的黑色恐怖距离就是 ddd。对 K 先生来说,黑色恐怖距离越小就越恐怖,因此他每次在研发中心内移动时,都会计算该如何使用黑科技,才能让途中经过的房间,最小的黑色恐怖距离最大。作为 K 先生下属的你,打算编写一个程序,帮助 K 先生快速算出在最不恐怖的路径上,所经过的房间里黑色恐怖距离的最小值。
输入格式
FFF MMM NNN
RRR
p1p_1p1 q1q_1q1 r1r_1r1
p2p_2p2 q2q_2q2 r2r_2r2
⋮\vdots⋮
pRp_RpR qRq_RqR rRr_RrR
QQQ
a1a_1a1 b1b_1b1 c1c_1c1 x1x_1x1 y1y_1y1 z1z_1z1
a2a_2a2 b2b_2b2 c2c_2c2 x2x_2x2 y2y_2y2 z2z_2z2
⋮\vdots⋮
aQa_QaQ bQb_QbQ cQc_QcQ xQx_QxQ yQy_QyQ zQz_QzQ
- FFF 代表 G 公司研发中心的层数。
- MMM 代表 G 公司研发中心的列数。
- NNN 代表 G 公司研发中心的行数。
- RRR 代表 G 公司研发中心的餐厅数。
- (pi,qi,ri)(p_i, q_i, r_i)(pi,qi,ri) 代表 G 公司研发中心内第 iii 间餐厅的位置。
- QQQ 代表 K 先生计划移动的次数。
- (ai,bi,ci)(a_i, b_i, c_i)(ai,bi,ci) 代表 K 先生计划第 iii 次移动的起点。
- (xi,yi,zi)(x_i, y_i, z_i)(xi,yi,zi) 代表 K 先生计划第 iii 次移动的终点。
输出格式
d1∗d_1^*d1∗
d2∗d_2^*d2∗
⋮\vdots⋮
dQ∗d_Q^*dQ∗
- di∗d_i^*di∗ 代表 K 先生第 iii 次移动时,所有可能的路径中,最小黑色恐怖距离的最大值。
输入输出样例 #1
输入 #1
3 3 3
3
1 1 1
2 2 2
3 3 3
4
1 3 3 3 1 1
1 2 2 3 2 2
1 2 3 1 2 3
1 1 1 3 3 3
输出 #1
2
1
2
0
输入输出样例 #2
输入 #2
1 1 3
1
1 1 2
1
1 1 1 1 1 3
输出 #2
0
说明/提示
测试数据限制
- 1≤F≤2×1051 \le F \le 2\times10^51≤F≤2×105。
- 1≤M≤2×1051 \le M \le 2\times10^51≤M≤2×105。
- 1≤N≤2×1051 \le N \le 2\times10^51≤N≤2×105。
- 1≤FMN≤2×1051 \le FMN \le 2\times10^51≤FMN≤2×105。
- 1≤R≤FMN1 \le R \le FMN1≤R≤FMN。
- 1≤pi≤F1 \le p_i \le F1≤pi≤F。
- 1≤qi≤M1 \le q_i \le M1≤qi≤M。
- 1≤ri≤N1 \le r_i \le N1≤ri≤N。
- 1≤Q≤2×1051 \le Q \le 2\times10^51≤Q≤2×105。
- 1≤ai≤F1 \le a_i \le F1≤ai≤F。
- 1≤bi≤M1 \le b_i \le M1≤bi≤M。
- 1≤ci≤N1 \le c_i \le N1≤ci≤N。
- 1≤xi≤F1 \le x_i \le F1≤xi≤F。
- 1≤yi≤M1 \le y_i \le M1≤yi≤M。
- 1≤zi≤N1 \le z_i \le N1≤zi≤N。
- 对任意 i,j∈{1,2,…,R}i, j \in \{1, 2, \ldots, R\}i,j∈{1,2,…,R},若 i≠ji \ne ji=j,则 (pi,qi,ri)≠(pj,qj,rj)(p_i, q_i, r_i) \ne (p_j, q_j, r_j)(pi,qi,ri)=(pj,qj,rj)。
- 输入的数皆为整数。
评分说明
本题共有五组子任务,条件限制如下所示。
每一组可有一或多个测试数据,该组所有测试数据皆需答对才可获得该组分数。
子任务 | 分数 | 额外输入限制 |
---|---|---|
1 | 666 | F=R=1,MN≤100,Q≤100F = R = 1, MN \le 100, Q \le 100F=R=1,MN≤100,Q≤100 |
2 | 212121 | 对任意 i∈{1,2,…,Q}i \in \{1, 2, \ldots, Q\}i∈{1,2,…,Q},均有 (ai,bi,ci)=(xi,yi,zi)(a_i, b_i, c_i) = (x_i, y_i, z_i)(ai,bi,ci)=(xi,yi,zi) |
3 | 444 | FMN≤3000FMN \le 3000FMN≤3000 |
4 | 252525 | Q=1Q = 1Q=1 |
5 | 444444 | 无额外限制 |
BFS 重构树
三维转一维,F是层数,R是行,C是列。(f,r,c)转成(R×C)×f+C×r+c(R\times C)\times f + C \times r+c(R×C)×f+C×r+c。相邻的层(行、列)有无向边相连。
以所有餐厅为起点,BFS出各点到餐厅的距离dis[cur],即点权。
每个查询都是求:最大路径权,即路径经过的点的最小点权。我们令边权为两各端点的点权的较小者。
即最小边权最大化,用重构树。
代码
核心代码
#include <iostream>
#include <sstream>
#include <vector>
#include<map>
#include<unordered_map>
#include<set>
#include<unordered_set>
#include<string>
#include<algorithm>
#include<functional>
#include<queue>
#include <stack>
#include<iomanip>
#include<numeric>
#include <math.h>
#include <climits>
#include<assert.h>
#include<cstring>
#include<list>#include <bitset>
using namespace std;template<class T1, class T2>
std::istream& operator >> (std::istream& in, pair<T1, T2>& pr) {in >> pr.first >> pr.second;return in;
}template<class T1, class T2, class T3 >
std::istream& operator >> (std::istream& in, tuple<T1, T2, T3>& t) {in >> get<0>(t) >> get<1>(t) >> get<2>(t);return in;
}template<class T1, class T2, class T3, class T4 >
std::istream& operator >> (std::istream& in, tuple<T1, T2, T3, T4>& t) {in >> get<0>(t) >> get<1>(t) >> get<2>(t) >> get<3>(t);return in;
}template<class T1, class T2, class T3, class T4,class T5 >
std::istream& operator >> (std::istream& in, tuple<T1, T2, T3, T4,T5>& t) {in >> get<0>(t) >> get<1>(t) >> get<2>(t) >> get<3>(t) >> get<4>(t);return in;
}template<class T1, class T2, class T3, class T4, class T5,class T6 >
std::istream& operator >> (std::istream& in, tuple<T1, T2, T3, T4, T5,T6>& t) {in >> get<0>(t) >> get<1>(t) >> get<2>(t) >> get<3>(t) >> get<4>(t) >>get<5>(t);return in;
}template<class T = int>
vector<T> Read() {int n;cin >> n;vector<T> ret(n);for (int i = 0; i < n; i++) {cin >> ret[i];}return ret;
}
template<class T = int>
vector<T> ReadNotNum() {vector<T> ret;T tmp;while (cin >> tmp) {ret.emplace_back(tmp);if ('\n' == cin.get()) { break; }}return ret;
}template<class T = int>
vector<T> Read(int n) {vector<T> ret(n);for (int i = 0; i < n; i++) {cin >> ret[i];}return ret;
}template<int N = 1'000'000>
class COutBuff
{
public:COutBuff() {m_p = puffer;}template<class T>void write(T x) {int num[28], sp = 0;if (x < 0)*m_p++ = '-', x = -x;if (!x)*m_p++ = 48;while (x)num[++sp] = x % 10, x /= 10;while (sp)*m_p++ = num[sp--] + 48;AuotToFile();}void writestr(const char* sz) {strcpy(m_p, sz);m_p += strlen(sz);AuotToFile();}inline void write(char ch){*m_p++ = ch;AuotToFile();}inline void ToFile() {fwrite(puffer, 1, m_p - puffer, stdout);m_p = puffer;}~COutBuff() {ToFile();}
private:inline void AuotToFile() {if (m_p - puffer > N - 100) {ToFile();}}char puffer[N], * m_p;
};template<int N = 1'000'000>
class CInBuff
{
public:inline CInBuff() {}inline CInBuff<N>& operator>>(char& ch) {FileToBuf();ch = *S++;return *this;}inline CInBuff<N>& operator>>(int& val) {FileToBuf();int x(0), f(0);while (!isdigit(*S))f |= (*S++ == '-');while (isdigit(*S))x = (x << 1) + (x << 3) + (*S++ ^ 48);val = f ? -x : x; S++;//忽略空格换行 return *this;}inline CInBuff& operator>>(long long& val) {FileToBuf();long long x(0); int f(0);while (!isdigit(*S))f |= (*S++ == '-');while (isdigit(*S))x = (x << 1) + (x << 3) + (*S++ ^ 48);val = f ? -x : x; S++;//忽略空格换行return *this;}template<class T1, class T2>inline CInBuff& operator>>(pair<T1, T2>& val) {*this >> val.first >> val.second;return *this;}template<class T1, class T2, class T3>inline CInBuff& operator>>(tuple<T1, T2, T3>& val) {*this >> get<0>(val) >> get<1>(val) >> get<2>(val);return *this;}template<class T1, class T2, class T3, class T4>inline CInBuff& operator>>(tuple<T1, T2, T3, T4>& val) {*this >> get<0>(val) >> get<1>(val) >> get<2>(val) >> get<3>(val);return *this;}template<class T = int>inline CInBuff& operator>>(vector<T>& val) {int n;*this >> n;val.resize(n);for (int i = 0; i < n; i++) {*this >> val[i];}return *this;}template<class T = int>vector<T> Read(int n) {vector<T> ret(n);for (int i = 0; i < n; i++) {*this >> ret[i];}return ret;}template<class T = int>vector<T> Read() {vector<T> ret;*this >> ret;return ret;}
private:inline void FileToBuf() {const int canRead = m_iWritePos - (S - buffer);if (canRead >= 100) { return; }if (m_bFinish) { return; }for (int i = 0; i < canRead; i++){buffer[i] = S[i];//memcpy出错 }m_iWritePos = canRead;buffer[m_iWritePos] = 0;S = buffer;int readCnt = fread(buffer + m_iWritePos, 1, N - m_iWritePos, stdin);if (readCnt <= 0) { m_bFinish = true; return; }m_iWritePos += readCnt;buffer[m_iWritePos] = 0;S = buffer;}int m_iWritePos = 0; bool m_bFinish = false;char buffer[N + 10], * S = buffer;
};class CUnionFind
{
public:CUnionFind(int iSize) :m_vNodeToRegion(iSize){for (int i = 0; i < iSize; i++){m_vNodeToRegion[i] = i;}m_iConnetRegionCount = iSize;}CUnionFind(vector<vector<int>>& vNeiBo) :CUnionFind(vNeiBo.size()){for (int i = 0; i < vNeiBo.size(); i++) {for (const auto& n : vNeiBo[i]) {Union(i, n);}}}int GetConnectRegionIndex(int iNode){int& iConnectNO = m_vNodeToRegion[iNode];if (iNode == iConnectNO){return iNode;}return iConnectNO = GetConnectRegionIndex(iConnectNO);}void Union(int iNode1, int iNode2){const int iConnectNO1 = GetConnectRegionIndex(iNode1);const int iConnectNO2 = GetConnectRegionIndex(iNode2);if (iConnectNO1 == iConnectNO2){return;}m_iConnetRegionCount--;if (iConnectNO1 > iConnectNO2){m_vNodeToRegion[iConnectNO1] = iConnectNO2;}else{m_vNodeToRegion[iConnectNO2] = iConnectNO1;}}bool IsConnect(int iNode1, int iNode2){return GetConnectRegionIndex(iNode1) == GetConnectRegionIndex(iNode2);}int GetConnetRegionCount()const{return m_iConnetRegionCount;}//vector<int> GetNodeCountOfRegion()//各联通区域的节点数量//{// const int iNodeSize = m_vNodeToRegion.size();// vector<int> vRet(iNodeSize);// for (int i = 0; i < iNodeSize; i++)// {// vRet[GetConnectRegionIndex(i)]++;// }// return vRet;//}std::unordered_map<int, vector<int>> GetNodeOfRegion(){std::unordered_map<int, vector<int>> ret;const int iNodeSize = m_vNodeToRegion.size();for (int i = 0; i < iNodeSize; i++){ret[GetConnectRegionIndex(i)].emplace_back(i);}return ret;}
private:vector<int> m_vNodeToRegion;//各点所在联通区域的索引,本联通区域任意一点的索引,为了增加可理解性,用最小索引int m_iConnetRegionCount;
};
class CParents
{
public:CParents(vector<int>& vParent, long long iMaxDepth){int iBitNum = 0;for (; iMaxDepth; iBitNum++) {const auto mask = 1LL << iBitNum;if (mask & iMaxDepth) { iMaxDepth = iMaxDepth ^ mask; }}const int n = vParent.size();m_vParents.assign(iBitNum + 1, vector<int>(n, -1));m_vParents[0] = vParent;//树上倍增for (int i = 1; i < m_vParents.size(); i++){for (int j = 0; j < n; j++){const int iPre = m_vParents[i - 1][j];if (-1 != iPre){m_vParents[i][j] = m_vParents[i - 1][iPre];}}}}int GetParent(int iNode, int iDepth)const{int iParent = iNode;for (int iBit = 0; iBit < m_vParents.size(); iBit++){if (-1 == iParent){return iParent;}if (iDepth & (1 << iBit)){iParent = m_vParents[iBit][iParent];}}return iParent;}int GetLeve(int node)const {int leve = 0;for (int i = m_vParents.size() - 1; i >= 0; i--) {if (-1 == m_vParents[i][node]) { continue; }node = m_vParents[i][node];leve += (1 << i);}return leve;}inline int GetBitCnt()const { return m_vParents.size(); };inline const int& GetPow2Parent(int iNode, int n)const {return m_vParents[n][iNode];}//在leftNodeExclude的1到rightLeve级祖先中查找符合pr的最近祖先template<class _Pr>int FindFirst(int leftNodeExclude, int rightLeve, _Pr pr) {for (int iBit = GetBitCnt() - 1; iBit >= 0; iBit--) {const int iMask = 1 << iBit;if (!(iMask & rightLeve)) { continue; }if (pr(m_vParents[iBit][leftNodeExclude])) {return BFindFirst(leftNodeExclude, iBit, pr);}leftNodeExclude = m_vParents[iBit][leftNodeExclude];}return -1;}//在node的0到rightLeve级祖先中查找符合pr的最远祖先比node高多少层次,这些层次必须存在template<class _Pr>int FindEnd(int node, int rightLeve, _Pr pr) {int leve = 0;for (int iBit = GetBitCnt() - 1; iBit >= 0; iBit--) {const int iMask = 1 << iBit;if (!(iMask & rightLeve)) { continue; }if (!pr(m_vParents[iBit][node])) {return leve + BFindEnd(node, iBit, pr);}node = m_vParents[iBit][node];leve = leve ^ iMask;}return leve;}
protected://在leftNodeExclude的1到2^pow^级祖先中查找符合pr的最近祖先template<class _Pr>int BFindFirst(int leftNodeExclude, int pow, _Pr pr) {while (pow > 0) {const int& mid = m_vParents[pow - 1][leftNodeExclude];if (pr(mid)) {}else {leftNodeExclude = mid;}pow--;}return m_vParents[0][leftNodeExclude];}//在node的[0,2^pow^-1]级祖先中寻找符合的最后一个template<class _Pr>int BFindEnd(int node, int pow, _Pr pr) {int leve = 0;while (pow > 0) {pow--;const int& mid = m_vParents[pow][node];if (pr(mid)) {node = mid;leve = leve ^ (1 << pow);}else {}}return leve;}vector<vector<int>> m_vParents;
};class C2Parents : public CParents
{
public:C2Parents(vector<int>& vParent, const vector<int>& vDepth) :m_vDepth(vDepth), CParents(vParent, *std::max_element(vDepth.begin(), vDepth.end())){}int GetPublicParent(int iNode1, int iNode2)const{int leve0 = m_vDepth[iNode1];int leve1 = m_vDepth[iNode2];if (leve0 < leve1){iNode2 = GetParent(iNode2, leve1 - leve0);leve1 = leve0;}else{iNode1 = GetParent(iNode1, leve0 - leve1);leve0 = leve1;}if (iNode1 == iNode2) { return iNode1; }for (int iBit = GetBitCnt() - 1; iBit >= 0; iBit--) {const int iMask = 1 << iBit;if (iMask & leve0) {const int i1 = GetPow2Parent(iNode1, iBit);const int i2 = GetPow2Parent(iNode2, iBit);if (i1 == i2) {while (iBit > 0) {const int i3 = GetPow2Parent(iNode1, iBit - 1);const int i4 = GetPow2Parent(iNode2, iBit - 1);if (i3 != i4) {iNode1 = i3; iNode2 = i4;}iBit--;}return GetPow2Parent(iNode1, 0);}else {iNode1 = i1; iNode2 = i2; leve0 -= iMask;}}}return iNode1;}
protected:vector<vector<int>> m_vParents;const vector<int> m_vDepth;
};//template<class WT = int, class _Pr = greater<typename WT> > //gcc过不了
template<class WT = int, class _Pr = greater<int> >
class CReconstructionTree
{
public:CReconstructionTree(const int N, const vector<tuple<int, int, WT>>& edge, WT defaultW) : m_weight(2 * N - 1, defaultW), m_actNodeCnt(2 * N - 1, 1) {m_vEdgeToPoint.assign(edge.size(), -1);m_vPar.assign(2 * N - 1, -1);vector<int> vRoot(N), inxs(edge.size());iota(vRoot.begin(), vRoot.end(), 0);iota(inxs.begin(), inxs.end(), 0);sort(inxs.begin(), inxs.end(), [&](const int& i1, const int& i2) { return _Pr()(get<2>(edge[i1]), get<2>(edge[i2])); });int cnt = 0;CUnionFind uf(N);for (int inx : inxs) {auto& [u, v, w] = edge[inx];const int g1 = uf.GetConnectRegionIndex(u);const int g2 = uf.GetConnectRegionIndex(v);if (g1 == g2) { continue; }m_vPar[vRoot[g1]] = m_vPar[vRoot[g2]] = N + cnt;m_actNodeCnt[N + cnt] = m_actNodeCnt[vRoot[g1]] + m_actNodeCnt[vRoot[g2]];uf.Union(u, v);const int g = uf.GetConnectRegionIndex(u);vRoot[g] = N + cnt;m_weight[N + cnt] = w;m_vEdgeToPoint[inx] = N + cnt;cnt++;}m_mp = new CParents(m_vPar, 2 * N - 1);}int GetRegionSize(int node, WT w) {auto Check = [&](int node) {return _Pr()(m_weight[node], w) || (m_weight[node] == w); };int leve = m_mp->FindEnd(node, m_mp->GetLeve(node), Check);int gp = m_mp->GetParent(node, leve);return m_actNodeCnt[gp];};void ChangeWeight(int edge, int w) {const int pt = m_vEdgeToPoint[edge];if (-1 == pt) { return; }//此边被忽略m_weight[pt] = w; //边权的相对大小不能变,否则需要重新建立树}vector<int> m_vPar;vector<WT> m_weight;
protected:CParents* m_mp;vector<int> m_actNodeCnt, m_vEdgeToPoint;
};
class CBFSDis
{
public:CBFSDis(vector<vector<int>>& vNeiB, vector<int> start){m_vDis.assign(vNeiB.size(), m_iNotMayDis);queue<int> que;for (const auto& n : start){m_vDis[n] = 0;que.emplace(n);}while (que.size()){const int cur = que.front();que.pop();for (const auto next : vNeiB[cur]){if (m_iNotMayDis != m_vDis[next]){continue;}m_vDis[next] = m_vDis[cur] + 1;que.emplace(next);}}}
public:const int m_iNotMayDis = 1e9;vector<int> m_vDis;
};class CParentToNeiBo
{
public:CParentToNeiBo(const vector<int>& parents){m_vChild.resize(parents.size());for (int i = 0; i < parents.size(); i++){if (-1 == parents[i]){m_roots.emplace_back(i);}else{m_vChild[parents[i]].emplace_back(i);}}}vector<vector<int>> m_vChild;vector<int> m_roots;
};
class Solution {
public:vector<int> Ans(const int F, const int R, const int C, vector<tuple<int, int, int>>& rooms, vector<tuple<int, int, int, int, int, int>>& que) {const int N = F * R * C;auto Mask = [&](int f, int r, int c) {return R * C * f + C * r + c; };vector<vector<int>> neiBo(N);vector<tuple<int, int, int>> edge;auto Add = [&](int m, int m1) {neiBo[m].emplace_back(m1);neiBo[m1].emplace_back(m);edge.emplace_back(m, m1, -1);};for (int f = 0; f < F; f++) {for (int r = 0; r < R; r++) {for (int c = 0; c < C; c++) {const int m = Mask(f, r, c);if (f) {Add(m, m - R * C);}if (r) {Add(m, m - C);}if (c) {Add(m, m - 1);}}}}vector<int> start;for (const auto& [f, r, c] : rooms) {start.emplace_back(Mask(f - 1, r - 1, c - 1));}CBFSDis dis(neiBo, start);for (auto& [u, v, w] : edge) {w = min(dis.m_vDis[u], dis.m_vDis[v]);}CReconstructionTree<> rt(N, edge, INT_MAX / 2);CParentToNeiBo pnb(rt.m_vPar);auto leves = CBFSDis(pnb.m_vChild, pnb.m_roots).m_vDis;C2Parents mp2(rt.m_vPar, leves);vector<int> ans;for (const auto& [a, b, c, d, e, f] : que) {auto g = mp2.GetPublicParent(Mask(a - 1, b - 1, c - 1), Mask(d - 1, e - 1, f - 1));ans.emplace_back((g < N) ? dis.m_vDis[g] : rt.m_weight[g]);}return ans;}
};int main() {
#ifdef _DEBUGfreopen("a.in", "r", stdin);
#endif // DEBUGios::sync_with_stdio(0); cin.tie(nullptr); cout.tie(nullptr); int F, R, C;cin >> F >> R >> C;auto rooms = Read<tuple<int, int, int>>();auto que = Read<tuple<int, int, int,int,int,int>>();
#ifdef _DEBUGprintf("F=%d,R=%d,C=%d", F,R,C);Out(rooms, ",rooms=");Out(que, ",que=");//Out(B, ",B=");//Out(ope, ",ope=");
#endif // DEBUGauto res = Solution().Ans(F,R,C,rooms,que);for (const auto& i : res){cout << i << "\n";}return 0;
}
单元测试
int F,R,C;vector<tuple<int, int, int>> rooms;vector<tuple<int, int, int, int, int, int>> que;TEST_METHOD(TestMethod11){F = 3, R = 3, C = 3, rooms = { {1,1,1},{2,2,2},{3,3,3} }, que = { {1,3,3,3,1,1},{1,2,2,3,2,2},{1,
2,3,1,2,3},{1,1,1,3,3,3} };auto res = Solution().Ans(F, R, C, rooms, que);AssertV({ 2,1,2,0 }, res);}TEST_METHOD(TestMethod12){F = 1, R = 1, C = 3, rooms = { {1,1,2} }, que = { {1,1,1,1,1,3} };auto res = Solution().Ans(F, R, C, rooms, que);AssertV({ 0}, res);}
扩展阅读
我想对大家说的话 |
---|
工作中遇到的问题,可以按类别查阅鄙人的算法文章,请点击《算法与数据汇总》。 |
学习算法:按章节学习《喜缺全书算法册》,大量的题目和测试用例,打包下载。重视操作 |
有效学习:明确的目标 及时的反馈 拉伸区(难度合适) 专注 |
员工说:技术至上,老板不信;投资人的代表说:技术至上,老板会信。 |
闻缺陷则喜(喜缺)是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。 |
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。 |
如果程序是一条龙,那算法就是他的是睛 |
失败+反思=成功 成功+反思=成功 |
视频课程
先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771
如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176
测试环境
操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。