解题思路:
这题可以用优先队列解决
我们把所有石子距离自己的距离和石头可以扔出的最远距离构成一个优先级队列
这个队列的优先级为距离自己的距离,如果距离自己的距离相同,那么优先级为可以扔出的最远距离
这样我们可以构建出堆
#include <iostream>
#include <algorithm>
using namespace std;
struct Stone
{
int disFromMe;
int distance;
};
class StoneTree {
private:
Stone* data;
int size;
void update(int pos, int n) {
int min_pos = pos;
int lchild = 2 * pos + 1;
int rchild = 2 * pos + 2;
if (lchild < n && data[lchild].disFromMe <= data[min_pos].disFromMe) {
if (data[lchild].disFromMe == data[min_pos].disFromMe) {
if (data[lchild].distance < data[min_pos].distance) {
min_pos = lchild;
}
}
if (data[lchild].disFromMe < data[min_pos].disFromMe) {
min_pos = lchild;
}
}
if (rchild < n && data[rchild].disFromMe <= data[min_pos].disFromMe) {
if (data[rchild].disFromMe == data[min_pos].disFromMe) {
if (data[rchild].distance < data[min_pos].distance) {
min_pos = rchild;
}
}
if (data[rchild].disFromMe < data[min_pos].disFromMe) {
min_pos = rchild;
}
}
if (min_pos != pos) {
swap(data[min_pos], data[pos]);
update(min_pos, n);
}
}
public:
StoneTree(int length_data) {
data = new Stone[length_data];
size = 0;
}
~StoneTree() {
delete data;
}
Stone top() {
return data[0];
}
int getSize() {
return size+1;
}
void push(Stone value) {
data[size] = value;
int current = size;
int father = (current - 1) / 2;
if (size == 0) {
size = size + 1;
return;
}
while (data[current].disFromMe < data[father].disFromMe) {
swap(data[current], data[father]);
current = father;
father = (current - 1) / 2;
}
while (data[current].disFromMe == data[father].disFromMe) {
if (data[current].distance < data[father].distance) {
swap(data[current], data[father]);
current = father;
father = (current - 1) / 2;
}
else {
break;
}
}
size = size + 1;
return;
}
void pop() {
swap(data[0], data[size - 1]);
size = size - 1;
update(0, size);
}
void show() {
for (int i = 0; i < size; ++i) {
cout << data[i].disFromMe << " " << data[i].distance << endl;
}
}
};
然后我们依次将结点出队,然后判断,如果出队次序为奇数次,那么就将这个结点距离自己的距离更新为 距离自己的距离+扔出的距离,然后放回队列中,调整堆序性
如果出队次序为偶数次,那么直接不管即可
int main() {
StoneTree stonetre(100001);
int n;
cin >> n;
for (int i = 0; i < n; ++i) {
Stone sto;
cin >> sto.disFromMe >> sto.distance;
stonetre.push(sto);
}
int index = 1; //判断出队次序是奇数次还是偶数次
while (stonetre.getSize() > 1) {
Stone tsto = stonetre.top();
stonetre.pop();
if (index % 2 == 1) {
tsto.disFromMe =tsto.disFromMe + tsto.distance;
stonetre.push(tsto);
index++;
}
else {
index++;
}
}
cout << stonetre.top().disFromMe << endl;
system("PAUSE");
return 0;
}