HDU - 1896 : Stones(优先队列、有序对)

8 篇文章 0 订阅
1 篇文章 0 订阅

题目链接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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值