多校第六场 1009 hdu 5361 In Touch(贪心+STL)

题目链接:

hdu 5361


题目大意:

给出以一些在同一直线上的点,其中每个点i可以走到与它之间的距离在 [liri] 区间的点,每次传送的花费是 ci ,那么问从0到达任意一点的最小花费。


题目分析:

  • 首先因为起点固定,且到达每个点的花费都为正数,我们维护一个set,储存一个点,排序的权值是它的最优解+到下一点的花费,其中的越早到达set的顶部,会先从集合中取出的点的花费一定更小,所以某个点早到达一定会比晚到达获得更优的解。然后已经得到最优解的点放入set,然后继续更新,直到所有的点都被更新。
  • 两个集合set1,set2,一个集合用来存储id,一个用来存当前的权值最小的集合。

AC代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#define MAX 200007

using namespace std;
typedef long long LL;

struct State
{
    int id;
    LL cost;
    State (){}
    State ( int a , LL b )
    {
        id = a;
        cost = b;
    }
    bool operator < ( const State& a ) const
    {
        if ( cost == a.cost ) return id < a.id;
        return cost < a.cost;
    }
};

int t,n;
int l[MAX],r[MAX];
LL c[MAX];
set<int> point;
set<State> state;
LL dis[MAX];

int main ( )
{
    scanf ( "%d" , &t );
    while ( t-- )
    {
        state.clear();
        point.clear();
        scanf ("%d" , &n );
        for ( int i = 0 ; i < n ; i++ )
            scanf ( "%d" , &l[i] );
        for ( int i = 0 ; i < n ; i++ )
            scanf ( "%d" , &r[i] );
        for ( int i = 0 ; i < n ; i++ )
            scanf ( "%I64d" , &c[i] );
        memset ( dis , -1 , sizeof ( dis ));
        dis[0] = 0;
        state.insert ( State ( 0 , c[0] ) );
        for ( int i = 1 ; i < n ; i++ )
            point.insert ( i );
        set<int>::iterator it1,it2;
        while ( !state.empty() )
        {
            State top = *(state.begin());
            int id = top.id;
            LL cost = top.cost;
            state.erase ( state.begin());
            it1 = point.lower_bound ( id- r[id] );
            while ( it1 != point.end() && *it1 <= id-l[id] )
            {
                State temp;
                temp.id = *it1;
                temp.cost = c[*it1]+cost;
                state.insert ( temp );
                dis[*it1] = cost;
                it2 = it1++;
                point.erase ( it2 );
            }
            it1 = point.lower_bound ( id + l[id] );
            while ( it1 != point.end() && *it1 <= id+r[id] )
            {
                State temp;
                temp.id = *it1;
                temp.cost = c[*it1]+cost;
                state.insert ( temp );
                dis[*it1] = cost;
                it2 = it1++;
                point.erase ( it2 );
            }
        }
        for ( int i = 0 ; i < n ; i++ )
        {
            if ( i ) printf ( " ");
            printf ( "%I64d" , dis[i] );
        }
        puts ( "" );
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值