我需要帮助确定我的此问题解决方案出了什么问题

I need help determining what is wrong with my solution to this problem

提问人:Jore 提问时间:11/12/2023 最后编辑:Jore 更新时间:11/13/2023 访问量:80

问:

这是我想在 C 中解决的问题:

问题

A国和B国之间爆发了一场战争,A国想通过空中轰炸摧毁首都B。但由于战争的突然爆发,双方的弹药储备都很低。由于弹药数量较少,战斗机飞行员杰夫被要求携带摧毁整个城市所需的确切数量的炸弹。每枚炸弹只能投掷到建筑物上。

B国的首都是一个有一维城市,有n座建筑物,其中每座建筑物(i)位于x轴上的某个x(i)处。杰夫必须摧毁城市中的每座建筑物。每枚炸弹都有一个破坏范围 k,这意味着它可以摧毁距离其撞击点 ≤ k 个单位的所有东西。

现在给定了城市地图和炸弹的射程k,杰夫希望你找到他摧毁整个城市所需的最小炸弹数量(每座建筑物必须在至少一枚炸弹的破坏范围内)。

输入

第一行包含两个空格分隔的整数 n(城市中的建筑物数量)和 k(每枚炸弹的破坏范围)。 第二行包含 n 个以空格分隔的整数,表示建筑物在 x 轴上的位置。

输出

打印一个整数,表示摧毁城市所需的最小炸弹数量。

约束

1 ≤ n,k ≤ 10^5
1 ≤ x ≤ 10^5

示例输入

4 2
1 2 3 4

示例输出

1

链接到问题。

问题也可以在以下位置找到:code.dcoder.tech >挑战>硬>耗尽弹药


我的解决方案

#include <stdio.h>
#include <stdlib.h>

/* Variables named according to the problem
 * n         - number of buildings
 * k         - range of bombs
 * buildings - Array containing the integer
 *             coordinates of the buildings
 */
int n, k, *buildings;

void getInput(void);
int isBuilding(int);
int nextBuilding(int);
int lastBuilding(int);

int main(void) {
 getInput();
 int bombs = 0;
 /* Loops through the x cordinates from building 1 to n
  * i - indicates the x coordinate where jeff is
  * j - indicates the bombed area
  * r - indicates the bomb range
  */
 for (int i = buildings[0], j = (buildings[0] - 1), r = k; i <= buildings[n - 1] || j < buildings[n - 1]; i++, r--) {
  /* When joel leaves bomb range coordinates behind */
  if (r == 0) {
   /* Bomb is only dropped on a building */
   while (!isBuilding(i))
    i--;
   /* Increment bombed area (back, position and front)*/
   j = i + k;
   bombs++;
   r = k + 1; // +1 because the loop makes r--
   /* next building beyond range
    * +1 because we need to leave all bombed area behind
    */
   i = nextBuilding(i + k + 1);
   /* if no building */
   if (i == 0)
    break;
   else
    i--; // the loop will make i++
  }
 }
 printf("%d\n", bombs);
 return 0;
}

/* Ascending comparison for qsort */
int compare(const void *a, const void *b) {
 const int *aa = a;
 const int *bb = b;
 return (*aa > *bb) - (*aa < *bb);
}

/* Gets input for n, k and buildings,
 * and sorts buildings
 */
void getInput(void) {
 if (scanf("%d %d", &n, &k) != 2) {
  fprintf(stderr, "input error\n");
  return;
 }
 buildings = calloc(sizeof *buildings, n);
 if (!buildings) {
  fprintf(stderr, "allocation error\n");
  return;
 }
 for (int i = 0; i < n; i++) {
  if (scanf("%d", &buildings[i]) != 1) {
   fprintf(stderr, "input error\n");
   return;
  }
 }
 qsort(buildings, n, sizeof *buildings, compare);
}

/* Returns 1 if it is a building,
 *  0 otherwise
 */
int isBuilding(int p) {
 for (int i = 0; i < n; i++) {
  if (buildings[i] == p)
   return 1;
 }
 return 0;
}

/* Returns position of next building greater or equal to p,
 * 0 if none available
 */
int nextBuilding(int p) {
 for (int i = 0; i < n; i++) {
  if (buildings[i] >= p)
   return buildings[i];
 }
 return 0;
}

/* Returns position of last building less or equal to p
 * 0 if none available
 */
int lastBuilding(int p) {
 for (int i = 0; i < n; i++) {
  if (buildings[i] == p)
   return buildings[i];
  else if (buildings[i] > p)
   return buildings[--i];
 }
 return 0;
}

解释

我采取更直接的方法解决这个问题,因为试图找到一个公式似乎是不可能的。

我主要使用杰夫的位置,他向前移动(炸弹射程)距离,然后在那里放置炸弹,如果当时有建筑物,或者回到最后一栋建筑物。(这个问题明确提到炸弹只能放置在建筑物上)。ik

然后我移动到下一个未被轰炸的建筑物并重复上述过程。i

条件是当有剩余的建筑物但无法满足(已超过最后一栋建筑物)时。j < ni <= buildings[n - 1]i

问题

代码在我这边似乎运行良好。

除了问题中的输入之外,我还测试了各种输入(如下所示),并得到了所需的输出。

Input:
6 2
1 2 3 4 5 6
Output: 2

Input:
10 2
2 3 8 16 17 18 19 20 21 22
Output: 4

尽管当我提交问题时,所有测试都失败了

我哪里出错了?

C 算法

评论

0赞 Peter - Reinstate Monica 11/12/2023
我喜欢这些现实生活中的例子!使编程变得更加有趣和相关。我有几点建议:增加可以摧毁的最大医院数量,并最大限度地提高平民/军人死亡率。另外,如果你有步兵,有多少村庄是触手可及的,这样你就可以在敌人的军队被动员起来之前屠杀他们的居民。如果你只是简单地把这个地方炸掉,你能节省多少钱,这是一个额外的问题,但问这个问题的老师受到了训斥。
0赞 Jore 11/13/2023
@Peter-恢复莫妮卡,请再读一遍问题。谢谢
0赞 Jore 11/13/2023
我已投票赞成结束这个问题。
0赞 Peter - Reinstate Monica 11/13/2023
你投票决定关闭自己的问题吗?我想这是可能的,但我也认为每个用户都可以简单地删除自己的问题。尽管我年纪相对较大(60岁),而且通常很随和,但我受到当前战争的影响,这些战争似乎异常残酷。(可能只是因为它们在政治和地理上比其他一些同样残暴的冲突更接近,但仍然如此。如果你明白我的意思,你的问题不知何故“让我发痒”。我认为这很有趣,也许你可以改写它。
0赞 Peter - Reinstate Monica 11/19/2023
一个问题可能是实现可能有 16 位整数,INT_MAX==32767,而最大值为 10^5,即 100000。我不知道这是否是重点,但它可能是。

答:

0赞 Jore 11/13/2023 #1

问题不在于代码,而在于网站对 C 解决方案的解释。

java 重新编写解决方案解决了这个问题。

评论

0赞 Peter - Reinstate Monica 11/13/2023
嗯......这是不令人满意的。最有可能的是,存在差异,例如在整数值范围等方面,这会导致 C 中的溢出错误,但在 Java 中则不然。我认为如果你只是继续下去,你就错过了实际的问题(在 Java 中“意外”解决了)。这些编程问题网站通常存在一些问题,这些问题具有简单、直接的解决方案,但运行时间过长,导致溢出或需要太多内存。看到并防止这种情况是实际问题。密切关注问题参数的取值范围,并测试一些极端值。
0赞 Peter - Reinstate Monica 11/13/2023
哦,如果你被困住了,你经常可以通过查看其他人的解决方案来“作弊”。
0赞 Jore 11/19/2023
@Peter-恢复莫妮卡 谢谢你的信息...我不知道整数范围问题。但是当我说它是网站时,请相信我。因为所有 C 解决方案都失败了(不是我尝试的最后一个),并且我针对多个输入测试了我的代码。奇怪的是,当我提交时,所有测试用例都失败了。(我的意思是至少有些应该是正确的)
0赞 Jore 11/19/2023
@Peter-恢复莫妮卡,我真的不喜欢作弊的部分。它违背了解决问题的全部意义。(获得一个有价值的挑战:-))我喜欢那些让我思考的算法问题
0赞 Peter - Reinstate Monica 11/19/2023
当然,这就是乐趣所在。另一方面,它也与学习有关。简单地复制别人的解决方案不是重点,但让它成为你自己的解决方案并理解问题才是重点。画家可以从临摹古代大师的作品中学习;程序员可以从查看出色的代码中学习。