#include <bits/stdc++.h>
// 定义 solve 函数来解决挖矿问题
void solve()
{
int n, m;
// 从标准输入读取矿洞数量 n 和最大移动距离 m
std::cin >> n >> m;
// s 用于记录坐标为 0 的矿洞数量
int s = 0;
// 定义两个静态数组 l 和 r 来分别记录负半轴和正半轴矿洞的前缀和
// 数组大小为 m + 1,初始化为 0
int l[10000001] = {0};
int r[10000001] = {0};
// 遍历每个矿洞
for (int i = 0; i < n; ++i)
{
int x;
// 读取当前矿洞的坐标
std::cin >> x;
// 如果矿洞坐标的绝对值小于等于最大移动距离 m 且为负数
//abs为绝对值函数
if (std::abs(x) <= m && x < 0)
{
// 对应负半轴的位置计数加 1
l[-x]++;
}
// 如果矿洞坐标的绝对值小于等于最大移动距离 m 且为正数
else if (std::abs(x) <= m && x > 0)
{
// 对应正半轴的位置计数加 1
r[x]++;
}
// 如果矿洞坐标为 0
else if (x == 0)
{
// 坐标为 0 的矿洞数量加 1
s++;
}
}
// 计算负半轴矿洞的前缀和
for (int i = 1; i <= m; ++i)
{
l[i] += l[i - 1];
}
// 计算正半轴矿洞的前缀和
for (int i = 1; i <= m; ++i)
{
r[i] += r[i - 1];
}
// 先假设最大矿石数为只走正半轴或只走负半轴能挖到的最大矿石数
int ans = std::max(r[m], l[m]);
// 尝试不同的左右移动组合,i 表示先向一个方向移动的距离
for (int i = 1; i <= m / 2; ++i)
{
// 先向右移动 i 的距离,再向左移动 m - i * 2 的距离能挖到的矿石数
int sr = r[i] + l[m - i * 2];
// 先向左移动 i 的距离,再向右移动 m - i * 2 的距离能挖到的矿石数
int sl = l[i] + r[m - i * 2];
// 更新最大矿石数
ans = std::max({ans, sr, sl});
}
// 加上坐标为 0 的矿洞数量
ans += s;
// 输出最大能获得的矿石数
std::cout << ans << '\n';
}
int main()
{
solve();
return 0;
}
2.C语言代码
cpp复制代码
#include <stdio.h>
#include <math.h>
#define MAX_M 10000001
// 定义 solve 函数来解决挖矿问题
void solve() {
int n, m;
// 从标准输入读取矿洞数量 n 和最大移动距离 m
scanf("%d %d", &n, &m);
// s 用于记录坐标为 0 的矿洞数量
int s = 0;
// 定义两个静态数组 l 和 r 来分别记录负半轴和正半轴矿洞的前缀和
// 数组大小为 MAX_M,初始化为 0
int l[MAX_M] = {0};
int r[MAX_M] = {0};
// 遍历每个矿洞
for (int i = 0; i < n; ++i) {
int x;
// 读取当前矿洞的坐标
scanf("%d", &x);
// 如果矿洞坐标的绝对值小于等于最大移动距离 m 且为负数
if (abs(x) <= m && x < 0) {
// 对应负半轴的位置计数加 1
l[-x]++;
}
// 如果矿洞坐标的绝对值小于等于最大移动距离 m 且为正数
else if (abs(x) <= m && x > 0) {
// 对应正半轴的位置计数加 1
r[x]++;
}
// 如果矿洞坐标为 0
else if (x == 0) {
// 坐标为 0 的矿洞数量加 1
s++;
}
}
// 计算负半轴矿洞的前缀和
for (int i = 1; i <= m; ++i) {
l[i] += l[i - 1];
}
// 计算正半轴矿洞的前缀和
for (int i = 1; i <= m; ++i) {
r[i] += r[i - 1];
}
// 先假设最大矿石数为只走正半轴或只走负半轴能挖到的最大矿石数
int ans = (r[m] > l[m]) ? r[m] : l[m];
// 尝试不同的左右移动组合,i 表示先向一个方向移动的距离
for (int i = 1; i <= m / 2; ++i) {
// 先向右移动 i 的距离,再向左移动 m - i * 2 的距离能挖到的矿石数
int sr = r[i] + l[m - i * 2];
// 先向左移动 i 的距离,再向右移动 m - i * 2 的距离能挖到的矿石数
int sl = l[i] + r[m - i * 2];
// 更新最大矿石数
if (sr > ans) ans = sr;
if (sl > ans) ans = sl;
}
// 加上坐标为 0 的矿洞数量
ans += s;
// 输出最大能获得的矿石数
printf("%d\n", ans);
}
int main() {
solve();
return 0;
}