关于“坠落的蚂蚁”这道题。一开始我尝试用追踪记录每一只蚂蚁的状态的方法解题,代码写了很长,最后只有40%的用例通过了检验,折腾了半天我也没发现到底错误在什么地方。代码:https://paste.ubuntu.com/p/q3GCtB2fw4/
这道题的一种简单思路如下:
1.静止蚂蚁的位置是固定不变的,即使蚂蚁相遇并发生了速度交换,永远都有一只蚂蚁处在初始静止蚂蚁A的位置。
2.假设A左侧蚂蚁都是向左的,右侧蚂蚁都是向右的,那么A必定不动,无法坠落。
3.左右移动的蚂蚁相遇时会交换速度,但从A的视角来看,是否交换速度对A的移动来说没有任何影响,可以看做两只蚂蚁互不影响继续前进。
4.综合2、3两点可以看出只有A左侧向右移动的蚂蚁和A右侧向左移动的蚂蚁会对A的移动产生影响。
5.当A左侧向右移动的蚂蚁和A右侧向左移动的蚂蚁数量相等时,A必定无法掉落。因为当A与距离其最近的LR(左侧向右)蚂蚁和RL(右侧向左)蚂蚁相遇之后,一定会回到静止状态。
6.当LR和RL蚂蚁不一样多时,A最终会继承较多一侧某蚂蚁的速度并且坠落,坠落时间等于该蚂蚁不受任何影响直线前进直至坠落的时间。
7.确定6中所指蚂蚁的方法,以LR蚂蚁较多为例:设RL蚂蚁数量为n,在LR蚂蚁中按初始位置从高到低数起,第n+1个LR蚂蚁即为所求蚂蚁。
启发:
当最终结果只关心某个元素时,可以考虑模糊其他元素的身份区别,只关心他们对所求元素的影响,将这种影响抽象出来作为解题思路可以大大降低编程难度。
追踪记录每个元素的方式不是不能用,在难以抽象的复杂情况下甚至可能会有更好的效果。但其缺点也很明显:当元素数量很多过程很长的时候,几乎不能用调试的方法找到其中细小的逻辑错误。这也是最终我只有40%通过率的原因。
代码:
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
struct ant{
int location;
int velocity;
};
bool Comp(ant a, ant b) {
return a.location < b.location;
}
int main() {
int n;
while (scanf("%d", &n) != EOF) {
ant Ants[n];
int Apos;
for (int i = 0; i < n; i++) {
scanf("%d %d", &Ants[i].location, &Ants[i].velocity);
if (Ants[i].velocity == 0) {
Apos = Ants[i].location;
}
} //输入结构体数组,记录A蚂蚁初始位置
vector<int>left, right; //定义两个容器分别存放A左侧向右蚂蚁,A右侧向左蚂蚁
sort(Ants, Ants + n, Comp);
for (int i = 0; i < n; i++) {
if (Ants[i].location < Apos && Ants[i].velocity == 1) {
left.push_back(Ants[i].location);
}
if (Ants[i].location > Apos && Ants[i].velocity == -1) {
right.push_back(Ants[i].location);
}
} //将LR和RL元素的位置加入容器中
if (left.size() == right.size()) {
printf("Cannot fall!");
}
else if (left.size() > right.size()) {
printf("%d", 100 - left[left.size() - right.size() - 1]);
}
else {
printf("%d", right[left.size()]);
}
}
}
京公网安备 11010502036488号