力扣杯春赛-个人赛 LCCUP’23

LCP 72. 补给马车

关键词:模拟

题目来源:LCP 72. 补给马车 - 力扣(Leetcode)

题目描述

 T模拟

远征队即将开启未知的冒险之旅,不过在此之前,将对补给车队进行最后的检查。supplies[i] 表示编号为 i 的补给马车装载的物资数量。 考虑到车队过长容易被野兽偷袭,他们决定将车队的长度变为原来的一半(向下取整),计划为:

  • 找出车队中 物资之和最小 两辆 相邻 马车,将它们车辆的物资整合为一辆。若存在多组物资之和相同的马车,则取编号最小的两辆马车进行整合;
  • 重复上述操作直到车队长度符合要求。

请返回车队长度符合要求后,物资的分布情况。

输入:supplies = [7,3,6,1,8]
输出:[10,15]
输入:supplies = [1,3,1,5]
输出:[5,5]
数据范围
2 <= supplies.length <= 1000
1 <= supplies[i] <= 1000

问题分析

观察数据范围,O(n^2)的时间复杂度是可以接受的,本题采用模拟即可。具体做法如下:

合并次数m=n-(n>>1),对于每次合并

  1. 扫描一遍数组,找到和最小的相邻两个元素,设为i,j
  2. 执行合并操作,即a[i]+=a[j];将j标记为不存在,即a[j]=0

最后,将剩余元素取出返回即可。

时间复杂度:O(n^2)

空间复杂度:O(n)

vector<int> supplyWagon(vector<int> &supplies) {int n = supplies.size(), m = n - (n >> 1);// m次合并while (m--) {// 找到和最小的相邻两个元素int sum = INT_MAX, mi, mj;for (int i = 0, j; i < n; i = j) {// 相邻两个元素i和jwhile (i < n && supplies[i] == 0)i++;j = i + 1;while (j < n && supplies[j] == 0)j++;// 比较和if (j < n && supplies[i] + supplies[j] < sum) {sum = supplies[i] + supplies[j], mi = i, mj = j;}}// 合并supplies[mi] += supplies[mj], supplies[mj] = 0;}// 将剩余元素取出vector<int> ans;for (const auto &e: supplies) {if (e != 0)ans.push_back(e);}return ans;
}

LCP 73. 探险营地

关键词:字典树、STL

题目来源:LCP 73. 探险营地 - 力扣(Leetcode)

问题描述

 T字典树TSTL

探险家小扣的行动轨迹,都将保存在记录仪中。expeditions[i] 表示小扣第 i 次探险记录,用一个字符串数组表示。其中的每个「营地」由大小写字母组成,通过子串 -> 连接。

例:“Leet->code->Campsite”,表示到访了 “Leet”、“code”、“Campsite” 三个营地。

expeditions[0] 包含了初始小扣已知的所有营地;对于之后的第 i 次探险(即 expeditions[i] 且 i > 0),如果记录中包含了之前均没出现的营地,则表示小扣 新发现 的营地。

请你找出小扣发现新营地最多且索引最小的那次探险,并返回对应的记录索引。如果所有探险记录都没有发现新的营地,返回 -1

注意:

  • 大小写不同的营地视为不同的营地;
  • 营地的名称长度均大于 0
输入:expeditions = ["leet->code","leet->code->Campsite->Leet","leet->code->leet->courier"]
输出:1
输入:expeditions = ["Alice->Dex","","Dex"]
输出:-1
输入:expeditions = ["","Gryffindor->Slytherin->Gryffindor","Hogwarts->Hufflepuff->Ravenclaw"]
输出:2
数据范围
1 <= expeditions.length <= 1000
0 <= expeditions[i].length <= 1000
探险记录中只包含大小写字母和子串"->"

问题分析

本题的核心问题就是:对于统计s[i]中有多少个“子串”没在s[0…1]中出现过。对于“查找字符串是否出现过”这类问题,很自然就想到字典树。若不采用字典树,可直接借助STL中的set。

字典树—数组

若采用字典树,对于本题而言,查询和插入可同时进行。

这里存在一个问题:N该指定多大呢?一般来说,最多有多少个结点,N就指定为多大,根据题目给出的数据范围,N应该为1e6(实际应比1e6稍大,避免越界),但是,这显然会超内存。经过测试,N大概可以到4e5,不会超内存且能通过本题,可以说,非常侥幸。

const int N = 4e5 + 5;
int son[N][52], n;
bool fg[N];/*** 查看字符串s是否存在,不存在则将其插入字典树中*/
bool check(const string &s) {int p = 0, u;for (auto &c: s) {u = c < 'a' ? c - 'A' : c - 'a' + 26;if (!son[p][u])son[p][u] = ++n;p = son[p][u];}if (fg[p])return true;  // 已存在fg[p] = true;           // 标记已存在return false;           // 原先不存在
}

写好字典树相关的代码,后面只需要遍历统计就可以了。

/*** 检查s中有多少子串还不存在*/
int count(const string &s) {int cnt = 0;if (!s.empty()) {int i, j;for (i = 0, j = s.find('-'); j != string::npos; i = j + 2, j = s.find('-', i)) {if (!check(s.substr(i, j - i))) cnt++;}if (!check(s.substr(i)))cnt++;}return cnt;
}
int adventureCamp(vector<string> &expeditions) {// 将初始字符串插入字典树count(expeditions[0]);// 找到发现新营地最多的那次探险int len = expeditions.size(), maxCam = 0, idx = -1, curCam;for (int i = 1; i < len; i++) {curCam = count(expeditions[i]);if (curCam > maxCam)maxCam = curCam, idx = i;}return idx;
}

时间604 ms 内存120.4 MB

字典树—指针

前面采用数组的方式,需要预先指定数组大小,所以,我们可以采用指针,动态分配结点。

struct Node {Node *child[52]{nullptr};bool vis{false};
} *root;/*** 查看字符串s是否存在,不存在则将其插入字典树中*/
bool check(const string &s) {auto p = root;int u;for (const char &c: s) {// 映射到0~52u = c < 'a' ? c - 'A' : c - 'a' + 26;if (p->child[u] == nullptr) {p->child[u] = new Node();}p = p->child[u];}if (p->vis)return true; // 已存在p->vis = true;          // 标记已存在return false;           // s原先不存在
}

需要注意的是,采用指针的方式所占用的内存会比采用数组的方式多不少。

int count(const string &s){// 同上
}
int adventureCamp(vector<string> &expeditions) {// 同上
}

时间620 ms 内存529.3 MB

STL—set集合

本题的核心操作就是判断一个字符串是否存在,因此,可以直接利用set来存放已存在的的字符串

/*** 检查s中有多少子串还不存在*/
int count(const string &s) {int cnt = 0;if (!s.empty()) {int i, j;string ts;for (i = 0, j = s.find('-'); j != string::npos; i = j + 2, j = s.find('-', i)) {ts = s.substr(i, j - i);if (st.find(ts) == st.end()) {st.insert(ts), cnt++;}}ts = s.substr(i);if (st.find(ts) == st.end()) {st.insert(ts), cnt++;}}return cnt;
}

虽然这可以算作暴力做法,但无论是在时间还是在空间上,都远优于字典树。

int adventureCamp(vector<string> &expeditions) {// 同上
}

时间316 ms 内存53.2 MB

LCP 74. 最强祝福力场

关键词:差分、前缀和、线段树、扫描线

题目来源:LCP 74. 最强祝福力场 - 力扣(Leetcode)

题目描述

 T差分T前缀和T线段树T扫描线

小扣在探索丛林的过程中,无意间发现了传说中“落寞的黄金之都”。而在这片建筑废墟的地带中,小扣使用探测仪监测到了存在某种带有「祝福」效果的力场。 经过不断的勘测记录,小扣将所有力场的分布都记录了下来。forceField[i] = [x,y,side] 表示第 i 片力场将覆盖以坐标 (x,y) 为中心,边长为 side 的正方形区域。

若任意一点的 力场强度 等于覆盖该点的力场数量,请求出在这片地带中 力场强度 最强处的 力场强度

**注意:**力场范围的边缘同样被力场覆盖。

输入: forceField = [[0,0,1],[1,0,1]]
输出:2

输入: forceField = [[4,4,6],[7,5,3],[1,6,2],[5,6,3]]
输出:3

数据范围
1 <= forceField.length <= 100
forceField[i].length == 3
0 <= forceField[i][0], forceField[i][1] <= 10^9
1 <= forceField[i][2] <= 10^9

问题分析

粗略一看,本题需要用扫描线来做,但是,观察数据范围发现,正方形的数量较少,正方形可能很大,对于这种“量少值大”的情况,极有可能使用到离散化,而离散化通常又和前缀和/差分一起出现,于是思考,能否使用前缀和和差分来解决此题。

题目要求的是被覆盖次数最多的点的被覆盖次数,对于每个正方形而言,其可以使得范围内的所有点的被覆盖次数+1,朴素想法就是,就出所有点被覆盖的次数,求最大值,便是本题的答案。而将一个矩形范围内的元素统一进行+1操作,这正是二维差分所擅长的。

但是,本题的坐标值非常的大,因此需要将坐标离散化,且是有序离散化。那离散化会不会影响答案呢?

证明:离散化不影响答案

设点p为力场强度最强的点,则必然存在这样一个最小矩形,其包含点p,且矩形内所有的点的力场强度均相等。注意,这样的矩形不一定是题目所给的矩形,而是由题目所给矩形的边围成的矩形,且可能是一条线,且p可能在矩形边上。

于是,必然存在一点q,其力场强度是最强的,且位于某个题目所给矩形的边上。

设t是题目所给的任意矩形的任意边上的任意一点,进行有序离散化后:

  • 原本在yt下边的横线仍在yt下边
  • 原来在yt上边的横线仍在yt上边
  • 原来在xt左边的竖线仍在xt左边
  • 原来在xt右边的竖线仍在xt右边

也即,点t被覆盖的次数并没有变,而对于其余非边上点,进行离散化后已全部被剔除,故最终的答案不变,证毕。

时间复杂度:O(n^2)

空间复杂度:O(n^2)

代码实现

注意int溢出问题

typedef long long ll;const int N = 2e2 + 5;
ll x[N], y[N];
int g[N][N], nx, ny;/*** 离散化(从1开始)*/
int find(ll u, bool isX) {return isX ?lower_bound(x, x + nx, u) - x + 1:lower_bound(y, y + ny, u) - y + 1;
}int fieldOfGreatestBlessing(vector<vector<int>> &forceField) {int n = forceField.size();// 记录所有出现的x坐标、y坐标for (int i = 0; i < n; i++) {auto &v = forceField[i];v[0] <<= 1, v[1] <<= 1;x[i << 1] = v[0] - v[2], x[i << 1 | 1] = (ll) v[0] + v[2];y[i << 1] = v[1] - v[2], y[i << 1 | 1] = (ll) v[1] + v[2];}// 排序去重n <<= 1;sort(x, x + n), sort(y, y + n);nx = unique(x, x + n) - x, ny = unique(y, y + n) - y;// 二维差分int x1, y1, x2, y2;for (auto &v: forceField) {// 离散化x1 = find(v[0] - v[2], true);x2 = find((ll) v[0] + v[2], true);y1 = find(v[1] - v[2], false);y2 = find((ll) v[1] + v[2], false);// 差分g[x1][y1]++, g[x2 + 1][y2 + 1]++;g[x1][y2 + 1]--, g[x2 + 1][y1]--;}// 找到被覆盖最多的点int maxCover = 0;for (int i = 1; i <= nx; i++) {for (int j = 1; j <= ny; j++) {g[i][j] += g[i - 1][j] + g[i][j - 1] - g[i - 1][j - 1];maxCover = max(g[i][j], maxCover);}}return maxCover;
}

LCP 75. 传送卷轴

关键词:单源最短路、深度优先、广度优先

题目来源:LCP 75. 传送卷轴 - 力扣(Leetcode)

题目描述

 T单源最短路T深度优先T广度优先

随着不断的深入,小扣来到了守护者之森寻找的魔法水晶。首先,他必须先通过守护者的考验。

考验的区域是一个正方形的迷宫,maze[i][j] 表示在迷宫 ij 列的地形:

  • 若为 . ,表示可以到达的空地;
  • 若为 # ,表示不可到达的墙壁;
  • 若为 S ,表示小扣的初始位置;
  • 若为 T ,表示魔法水晶的位置。

小扣每次可以向 上、下、左、右 相邻的位置移动一格。而守护者拥有一份「传送魔法卷轴」,使用规则如下:

  • 魔法需要在小扣位于 空地 时才能释放,发动后卷轴消失;;
  • 发动后,小扣会被传送到水平或者竖直的镜像位置,且目标位置不得为墙壁;

在使用卷轴后,小扣将被「附加负面效果」,因此小扣需要尽可能缩短传送后到达魔法水晶的距离。而守护者的目标是阻止小扣到达魔法水晶的位置;如果无法阻止,则尽可能 增加 小扣传送后到达魔法水晶的距离。 假设小扣和守护者都按最优策略行事,返回小扣需要在 「附加负面效果」的情况下 最少 移动多少次才能到达魔法水晶。如果无法到达,返回 -1

注意:

  • 守护者可以不使用卷轴;
  • 传送后的镜像位置可能与原位置相同。
输入:maze = [".....","##S..","...#.","T.#..","###.."]
输出:7
解释:守护者释放魔法的两个最佳的位置为 [2,0] 或 [3,1]: 若小扣经过 [2,0],守护者在该位置释放魔法, 小扣被传送至 [2,4] 处且加上负面效果,此时小扣还需要移动 7 次才能到达魔法水晶; 若小扣经过 [3,1],守护者在该位置释放魔法, 小扣被传送至 [3,3] 处且加上负面效果,此时小扣还需要移动 9 次才能到达魔法水晶; 因此小扣负面效果下最少需要移动 7 次才能到达魔法水晶。
输入:maze = [".#..","..##",".#S.",".#.T"]
输出:-1
解释: 若小扣向下移动至 [3,2],守护者使其传送至 [0,2],小扣将无法到达魔法水晶; 若小扣向右移动至 [2,3],守护者使其传送至 [2,0],小扣将无法到达魔法水晶;
输入:maze = ["S###.","..###","#..##","##..#","###.T"]
输出:5
解释:守护者需要小扣在空地才能释放,因此初始无法将其从 [0,0] 传送至 [0,4]; 当小扣移动至 [2,1] 时,释放卷轴将其传送至水平方向的镜像位置 [2,1](为原位置) 而后小扣需要移动 5 次到达魔法水晶
数据范围
4 <= maze.length == maze[i].length <= 200
maze[i][j] 仅包含 "."、"#"、"S"、"T"

问题分析

不难发现

  • 若在 「附加负面效果」的情况下移动不超过k步能到达魔法水晶,在不超过k+1步也能到达终点
  • 若在 「附加负面效果」的情况下移动不超过k步不能到达魔法水晶,在不超过k-1步也不能到达终点

因此k值具有单调性,可二分求解满足条件的k的最小值。

check(k)的任务就是,判断能否在 「附加负面效果」的情况下移动不超过k步到达魔法水晶,“是否存在通路”这类问题可采用dfs来做。

施加魔法后,需要直到新位置到达终点最少需要多少步,因此需要预处理出终点到每个位置的最短距离,“求最短通路”可采用bfs来做。

综上:bfs预处理出终点到每个点的最短距离,整体框架是二分,通过dfs判断是否存在通路。

时间复杂度:O( n2log(n) )

空间复杂度:O( n2 )

代码实现

typedef pair<int, int> P;
const int N = 2e2 + 5, INF = 0x3f3f3f3f;
int dx[] = {-1, 0, 1, 0}, dy[] = {0, -1, 0, 1};
P s, t;
int n, d[N][N];
bool vis[N][N];
/*** 初始化每个点到终点的最短距离*/
void initDis(vector<string> &maze) {memset(d, 0x3f, sizeof d);queue<P> q;int sep = d[t.first][t.second] = 0, u, v, lay;q.push(t);while (!q.empty()) {// 每遍历一层,与终点的距离便+1sep++, lay = q.size();// 当前层所有结点与终点的距离均为sepwhile (lay--) {// 取出队头结点P tp = q.front();// 拓展结点for (int i = 0; i < 4; i++) {u = tp.first + dx[i], v = tp.second + dy[i];if (u < 0 || u >= n || v < 0 || v >= n ||maze[u][v] == '#' || d[u][v] < INF)continue;if (u >= n || v >= n) {cout << "!!!";}d[u][v] = sep;q.push({u, v});}// 前面使用引用,所以要等到使用完后出队q.pop();}}
}
/*** 检查能否使得附加负面效果的步数不超过sep步到达终点*/
bool dfs(int sep, int x, int y, vector<string> &maze) {// 越界或障碍物或已访问if (x < 0 || x >= n || y < 0 || y >= n ||maze[x][y] == '#' || vis[x][y])return false;// 到达终点if (x == t.first && y == t.second)return true;if (x >= n || y >= n) {cout << "!!!";}// 标记已访问vis[x][y] = true;// 施展魔法// 体现守护者的最优策略if (maze[x][y] == '.') {// 如果能传送到一个使用sep不能到达终点的点,说明当前路在限制为sep的情况下不可if (maze[x][n - y - 1] != '#' && d[x][n - y - 1] > sep)return false;if (maze[n - x - 1][y] != '#' && d[n - x - 1][y] > sep)return false;}// 只要存在一条路在施加负面效果的情况下可在sep步内到达终点,说明sep步一定可到达终点// 体现小扣的最优策略for (int i = 0; i < 4; i++)if (dfs(sep, x + dx[i], y + dy[i], maze))return true;return false;
}
int challengeOfTheKeeper(vector<string> &maze) {n = maze.size();// 找到起点和终点for (int i = 0; i < n; i++)for (int j = 0; j < n; j++)if (maze[i][j] == 'S')s = {i, j};else if (maze[i][j] == 'T')t = {i, j};// 初始化每个点到终点的最短距离initDis(maze);// 起点无法到达终点if (d[s.first][s.second] >= INF)return -1;// 二分答案int l = 0, r = n * n, mid;while (l < r) {mid = (l + r) >> 1;memset(vis, 0, sizeof vis);if (dfs(mid, s.first, s.second, maze))r = mid;else l = mid + 1;}return l == n * n ? -1 : l;
}

LCP 76. 魔法棋盘

关键词:深度优先、状态压缩

在大小为 n * m 的棋盘中,有两种不同的棋子:黑色,红色。当两颗颜色不同的棋子同时满足以下两种情况时,将会产生魔法共鸣:

  • 两颗异色棋子在同一行或者同一列
  • 两颗异色棋子之间恰好只有一颗棋子

注:异色棋子之间可以有空位

由于棋盘上被施加了魔法禁制,棋盘上的部分格子变成问号。chessboard[i][j] 表示棋盘第 ij 列的状态:

  • 若为 . ,表示当前格子确定为空
  • 若为 B ,表示当前格子确定为 黑棋
  • 若为 R ,表示当前格子确定为 红棋
  • 若为 ? ,表示当前格子待定

现在,探险家小扣的任务是确定所有问号位置的状态(留空/放黑棋/放红棋),使最终的棋盘上,任意两颗棋子间都 无法 产生共鸣。请返回可以满足上述条件的放置方案数量。

输入:n = 3, m = 3, chessboard = ["..R","..B","?R?"]
输出:5
输入:n = 3, m = 3, chessboard = ["?R?","B?B","?R?"]
输出:105
数据范围
n == chessboard.length
m == chessboard[i].length
1 <= n*m <= 30
chessboard 中仅包含 "."、"B"、"R"、"?"

问题分析

考虑到数据范围较小,因此,可采用深搜来枚举每种方案。

对于位置(i,j)

  • 若为?,则将将其置为空/黑棋/红棋,放置是否合法,需要参考目前棋盘的状态
  • 若为.,则直接往后深搜即可,因为空位不影响结果。
  • 若为B或R,则需要判断目前的状态是否合法,若合法则往后深搜

从左往右从上到下的顺序(先列后行)搜索,每当搜完最后一个位置,便得到一种方案。

如何存放当前的状态呢?由于状态较多,一来要有助于快速判断是否合法,二来要节约空间,自然就想到状态压缩。

对于每一行/每一列,其合法的状态不外乎以下7类:

  • 空:即全为“.”
  • 仅一个B:如,“…B”,“…B…”
  • 仅一个R:如,“.R…”,“R.”
  • 多个B:如,“.B…B”,“…BB”
  • 多个R:如,“RR…”,“R…RR…R”
  • BR交替且结尾为B:如,“BRB…”,“…RB…”
  • BR交替且结尾为R:如,“RB…R…BR”,“…R…B…R…”

故可用3位二进制来表示所有合法的单行/列状态。

对于?,由于将其置空不影响状态,故只需考虑置黑棋和置红棋的情况,于是,可以预处理出一张状态转换表T,借助表T,可快速判断是否合法。

由于位置(i,j)能放什么,是否合法,仅与所在行和所在列有关,且按从左往右从上到下,故需要记录当前行和所有列的信息。每列用3位二进制表示,且可以保证列数不超过5,故可用15位二进制表示所有列的状态,也即一个整数即可。

代码实现

不带记忆化:能过大部分测试用例

typedef pair<int, int> P;const int N = 35;
char g[N][N];
int rn, cm;
long long ans;// 状态转换表
int T[7][2] = {// +B后的状态   +R后的状态{1,  2},     // 空{3,  6},      // 一个B{5,  4},      // 一个R{3,  -1},     // 多个B{-1, 4},     // 多个R{-1, 6},     // BR交替且以B结尾{5,  -1}      // BR交替且以R结尾
};
/*** 枚举(i,j)的所有可能值* rs:当前行的状态* state:0~2位存放第1列的状态,3~5位存放第2列的状态,12~14位存放第5列的状态*/
void dfs(int r, int c, int rs, int state) {// 最后一行的状态已被枚举完:得到一种方案if (r == rn) {ans++;return;}// 当前行已枚举完,开始枚举下一行if (c == cm) {dfs(r + 1, 0, 0, state);return;}// 存放下一状态P p = {rs, state};// 检查在(r,c)追加颜色为C的棋是否合理,合理则将新的状态保存到p中auto check = [&](int C) {int c3 = c * 3;if (T[rs][C] == -1 || T[(state >> c3) & 7][C] == -1)return false;p = {T[rs][C], state & ~(7 << c3) | (T[(state >> c3) & 7][C] << c3)};return true;};// 问号if (g[r][c] == '?') {// ?置为空:当前行和全局列的状态不改变dfs(r, c + 1, rs, state);// ?置为Bif (check(0))dfs(r, c + 1, p.first, p.second);// ?置为Rif (check(1))dfs(r, c + 1, p.first, p.second);return;}// 黑棋或红棋:判断是否与已经填充的冲突else if (g[r][c] == 'B' && !check(0) ||g[r][c] == 'R' && !check(1))return;// 空位||(黑棋或红棋合理)// 若为空位,则p就为初始状态// 若为黑棋或红棋合理,则p在check时就已被修改为新的状态dfs(r, c + 1, p.first, p.second);
}
long long getSchemeCount(int n, int m, vector<string> &chessboard) {// 确保m≤nif (n >= m) {rn = n, cm = m;for (int i = 0; i < n; i++)sscanf(chessboard[i].c_str(), "%s", g[i]);} else {rn = m, cm = n;for (int i = 0; i < n; i++)for (int j = 0; j < m; j++)g[j][i] = chessboard[i][j];}// 深搜dfs(0, 0, 0, 0);return ans;
}

带记忆化:能AC

typedef long long ll;
typedef pair<int, int> P;const int N = 32, M = 28087;
char g[N][N];
int rn, cm;
ll f[N][8][M];// 状态转换表
int T[7][2] = {// +B后的状态   +R后的状态{1,  2},     // 空{3,  6},      // 一个B{5,  4},      // 一个R{3,  -1},     // 多个B{-1, 4},     // 多个R{-1, 6},     // BR交替且以B结尾{5,  -1}      // BR交替且以R结尾
};
/*** 枚举(i,j)的所有可能值* rs:当前行的状态* state:0~2位存放第1列的状态,3~5位存放第2列的状态,12~14位存放第5列的状态* 返回目前状态为rs和state的情况下,从(i,j)开始枚举,得到的方案数*/
ll dfs(int r, int c, int rs, int state) {// 最后一行的状态已被枚举完:得到一种方案if (r == rn) return 1;// 当前行已枚举完,开始枚举下一行if (c == cm)return dfs(r + 1, 0, 0, state);// 记忆化ll &v = f[r * cm + c][rs][state];if (v != -1)return v;// 存放下一状态P p = {rs, state};// 检查在(r,c)追加颜色为C的棋是否合理,合理则将新的状态保存到p中auto check = [&](int C) {int c3 = c * 3;if (T[rs][C] == -1 || T[(state >> c3) & 7][C] == -1)return false;p = {T[rs][C], state & ~(7 << c3) | (T[(state >> c3) & 7][C] << c3)};return true;};// 问号if (g[r][c] == '?') {v = 0;// ?置为空:当前行和全局列的状态不改变v += dfs(r, c + 1, rs, state);// ?置为Bif (check(0))v += dfs(r, c + 1, p.first, p.second);// ?置为Rif (check(1))v += dfs(r, c + 1, p.first, p.second);return v;}// 黑棋或红棋:判断是否与已经填充的冲突else if (g[r][c] == 'B' && !check(0) ||g[r][c] == 'R' && !check(1))return v=0;// 空位||(黑棋或红棋合理)// 若为空位,则p就为初始状态// 若为黑棋或红棋合理,则p在check时就已被修改为新的状态return v = dfs(r, c + 1, p.first, p.second);
}
long long getSchemeCount(int n, int m, vector<string> &chessboard) {// 确保m≤nif (n >= m) {rn = n, cm = m;for (int i = 0; i < n; i++)sscanf(chessboard[i].c_str(), "%s", g[i]);} else {rn = m, cm = n;for (int i = 0; i < n; i++)for (int j = 0; j < m; j++)g[j][i] = chessboard[i][j];}// 深搜memset(f, -1, sizeof f);return dfs(0, 0, 0, 0);;
}

【算法竞赛】力扣杯春赛-个人赛 LCCUP‘23复盘相关推荐

  1. 力扣杯2023春-个人赛、战队赛

    文章目录 力扣杯2023春-个人赛 [LCP 72. 补给马车](https://leetcode.cn/problems/hqCnmP/) 模拟 [LCP 73. 探险营地](https://lee ...

  2. 【算法比赛】2020 力扣杯!Code Your Future 春季全国编程大赛

    这个比赛,除了最后一题,其他四题其实没啥难度. 第一题:模拟. 第二题:BFS 或者 DP. 第三题:二分. 第四题:BFS. 第五题:思维 + 树的 DFS. 详细题解如下. 1.拿硬币 AC代码( ...

  3. 力扣第三题java_LeetCode 题解 | 力扣杯 LCP 06. 拿硬币

    力扣杯 LCP 06. 拿硬币(点击查看题目) 力扣​leetcode-cn.com 题目描述 桌上有 n 堆力扣币,每堆的数量保存在数组 coins 中.我们每次可以选择任意一堆,拿走其中的一枚或者 ...

  4. 第十三届蓝桥杯省赛 python B组复盘(三道代码题全AC居然省一了)

    第十三届蓝桥杯省赛 python B组复盘(三道代码题全AC居然省一了)

  5. C++算法学习(力扣:328. 奇偶链表)

    给定一个单链表,把所有的奇数节点和偶数节点分别排在一起.请注意,这里的奇数节点和偶数节点指的是节点编号的奇偶性,而不是节点的值的奇偶性. 请尝试使用原地算法完成.你的算法的空间复杂度应为 O(1),时 ...

  6. C++算法学习(力扣:面试题 16.04. 井字游戏)

    设计一个算法,判断玩家是否赢了井字游戏.输入是一个 N x N 的数组棋盘,由字符" ","X"和"O"组成,其中字符" &quo ...

  7. C++算法学习(力扣:201. 数字范围按位与)

    给定范围 [m, n],其中 0 <= m <= n <= 2147483647,返回此范围内所有数字的按位与(包含 m, n 两端点). 示例 1: 输入: [5,7] 输出: 4 ...

  8. 【赛后诸葛】2020 力扣杯!Code Your Future 春季全国编程大赛

    目录 简介 1. 拿硬币 2. 传递信息 3. 剧情触发时间 4. 最小跳跃次数 5. 二叉树任务调度 简介 第一次参加leetcode的比赛,比赛结果比较惨淡.AC两道,然后就陷入了超时的困境.记录 ...

  9. 【数据结构与算法】力扣实战之移动零、盛最多的水、爬楼梯

    练题法则 5-10分钟读题与思考 不要纠结没有思路就直接看题解: 不要死磕觉得自己很失败,怎么我们就想不出来: 基本上这些算法题,让我们自己想出来是不可能的: 拿跳表的来说,如果我们能从0-1把它想出 ...

最新文章

  1. python【蓝桥杯vip练习题库】ALGO-189 P0505(阶乘问题)
  2. 设置AFNetworking网络请求的超时时间
  3. ubuntu让/etc/hosts修改后立刻生效
  4. SAP Commerce Cloud Spartacus UI 的 ActionClass 数据结构设计
  5. Linux-Centos 安装Anaconda(2021)
  6. @ApiImplicitParam注解的dataType、paramType两个属性的区别?
  7. 著名音频库多角度对比(多平台可用)
  8. IntelliJ IDEA设置代码提示(常用快捷键)
  9. 深度学习之RNN循环神经网络(理论+图解+Python代码部分)
  10. MySql安装root用户密码设置失败问题解决
  11. 结合thinkphp5与hplus(h+)写的一个带权限的后台管理系统
  12. 位移的单位符号_位移传感器符号
  13. 什么是properties文件
  14. Unity2D学习笔记Day12:敌人统一死亡动画+Class的继承(含虚函数virtual,重写override)
  15. matlab pid buck,基于MATLAB的BUCK电路设计与PID闭环仿真
  16. Arduino 播放音乐教程
  17. 金碟文件保存在服务器哪里,金蝶软件服务器地址在哪改
  18. template 的 用法
  19. 心灵成长的六个定律 (2) - By 武志红
  20. 2018 之后,Android 工程师将何去何从?

热门文章

  1. 阿里云服务器ECS-Apollo搭建MQTT服务器(Windows环境)
  2. 创建证书与Xcode破解
  3. 在职场|项目管理干货总结
  4. ffmpeg截取一段视频
  5. Python实现蒙塔卡洛思想
  6. 【考研经验】19年华东师范大学计算机专硕考研经验(初试+复试)分享!专业课140分!...
  7. 护眼灯到底有用吗?2022市面上这几款护眼灯真的能护眼
  8. 苹果手机密码设置在哪里_sim卡密码设置在哪里-sim卡密码设置介绍
  9. HTML 与 CSS
  10. 小米、360、萤石等智能摄像头如何选购?需要注意哪些功能信息