题目链接:HDU - 1896 : Stones
题意:路上有一些石头,首先告诉你石头的坐标,接下来玩个丢石头的游戏,你往前走遇到的第奇数个的石头可以丢,投掷距离和坐标同时给出,遇到的第偶数个的石头原地不动。但注意!当一个坐标同时有几个石头时,你先遇到的是投掷距离最近的石头(这一条件在判断哪个石头是第奇数个遇到的以及该不该扔时很重要,说白了就是影响优先级排序)。问这样下去,最后距离起点最远的石头是多远
思路:用优先队列模拟,每当遇到第奇数个石头,就将其坐标加上其投掷距离next.second,然后放回优先队列,由于这里有两个关键字,可以利用有序对,编写比较函数(位置第一,投掷距离第二)定义其优先级排序,当队列为空时输出最后一个位置即可
优先队列的优先级定义可参照:优先级定义
AC代码:
- 用有序对实现,比较函数是通过在新的结构体中重载函数对象来实现
#include<iostream>
#include<cstdio>
#include<utility>
#include<vector>
#include<queue>
using namespace std;
typedef pair<int,int> p;
struct cmp
{
bool operator ()(p a,p b)
{
if(a.first==b.first) return a.second>b.second;//第二关键字小的优先级高
else return a.first>b.first;//第一关键字小的优先级高
}
};
priority_queue<p,vector<p>,cmp> q;//优先队列
int main()
{
int t,n;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
while(!q.empty()) q.pop();
int pos,dis;
for(int i=0; i<n; i++)
{
scanf("%d%d",&pos,&dis);
q.push(p(pos,dis));
}
int num=1;//从第一个石头开始,之后奇数丢,偶数不丢
p nex;
while(!q.empty())
{
nex=q.top();
q.pop();
if(num&1) q.push(p(nex.first+nex.second,nex.second));
num++;
}
printf("%d\n",nex.first);
}
return 0;
}
- 如果觉得有序对用不惯的话,当然也可以用结构体了,这里采用结构体重载比较操作符实现排序
#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
using namespace std;
struct stone
{
int pos;//坐标作为第一关键字
int dis;//投掷距离作为第二关键字
stone(int pos, int dis):pos(pos),dis(dis){} //方便赋值
};
bool operator <(stone a,stone b)
{
if(a.pos==b.pos) return a.dis>b.dis;//位置坐标相同时,投掷距离小的优先
else return a.pos>b.pos;//坐标小的优先
}
priority_queue<stone> q;//优先队列
int main()
{
int t,n;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
while(!q.empty()) q.pop();
int pos,dis;
for(int i=0; i<n; i++)
{
scanf("%d%d",&pos,&dis);
q.push(stone(pos,dis));
}
int num=1;//从第一个石头开始,之后遇到的奇数丢,偶数不丢
stone nex(0,0);
while(!q.empty())
{
nex=q.top();
q.pop();
if(num&1) q.push(stone(nex.pos+nex.dis,nex.dis));
num++;
}
printf("%d\n",nex.pos);
}
return 0;
}