upc-Environment-Friendly Travel(分层图最短路)

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

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

题意

给你起点终点坐标,再给你最大的行走距离 b ,再给你私人汽车的排放量 c0(从起点到车站,从车站到终点都是坐私人汽车),然后再给你 t 种交通方式的排放量,最后给你 n 个车站的坐标,以及每个车站 i 可以通过 某种交通方式 m 到达车站 j .最后让你求能在行走距离不超过 b 的情况下,从起点到终点的最小排放量,如果到不了输出 -1。

思路

对于最大的行走距离 b 是一个很小的值,我们可以设 dis [ i ] [ j ] 为当前走到 x 节点,总行走距离为 j 的最小排放量.,跑一遍最短路,在 dis [ n + 1] [ i ] ( 0<=i<=b) 中取最小值就是答案
(训练的时候刘爷跟我说这个题我做过(类似的),当时我就懵了,然后我忽然就想起来,我跟着潘学长做过,但是当时没做出来,后来让我补题来着,但是当时我没有立刻补题,结果,,,我就给忘记了/(ㄒoㄒ)/~~,亏了鑫爷还写了博客,唉,这波又辜负学长们的关心了 ,可能这也是我被ybl大佬拉开的原因吧,以后要及时补题了,要不可能真的就凉凉了/(ㄒoㄒ)/~)

代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<cstring>
#include<algorithm>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=1e6+10;
const int mod=1e6+10;
int xs,xd,ys,yd,b,c0,t,n,l,cnt;
int c[1010],head[maxn],dis[1010][110];
bool vis[1010][110];
struct node
{
    int w;
    int to;
    int next;
}edge[maxn];
struct Node
{
    int id;
    int co2;
    int diss;
    friend bool operator < (const Node &a,const Node &b)
    //重载小于号使得小的先出队列  
    {
        if(a.co2==b.co2) return a.diss>b.diss;
        else return a.co2>b.co2;
    }
    //如果a.co2>b.co2成立,那么结构体Node a < Node b成立。
    //由于优先队列是按照从大到小排列,所以结构体b会排列到a之前,b先出
    //这里注释是因为我之前一直搞不懂关于对优先队列运算符的重载
    //正好借这个题好好理解一下o(╥﹏╥)o 
    Node(){}
    Node(int a,int b,int c)
    {
        id=a,co2=b,diss=c;
    }
};
pair<int,int>p[maxn];
void add(int u,int v,int w)
{
    edge[cnt].w=w;
    edge[cnt].to=v;
    edge[cnt].next=head[u];
    head[u]=cnt++;
}
void init()
{
    memset(head,-1,sizeof(head));
    memset(vis,0,sizeof(vis));
    memset(dis,INF,sizeof(dis));
    cnt=0;
}
int getdis(int a,int b)
{
    int x=p[a].first-p[b].first;
    int y=p[a].second-p[b].second;
    return ceil(sqrt(x*x+y*y));
}
void dijkstra()
{
    priority_queue<Node>q;
    dis[0][0]=0;q.push(Node(0,0,0)); 
    while(q.size())
    {
        int now=q.top().id;
        int ds=q.top().diss;
        q.pop();
        if(vis[now][ds]) continue;
        vis[now][ds]=1;
        for(int i=head[now];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            int diss=getdis(now,v);
            int co2=diss*c[edge[i].w];
            if(diss+ds>b) continue;//小优化 
            if(dis[v][diss+ds]>co2+dis[now][ds])
            { 
                dis[v][diss+ds]=co2+dis[now][ds];
                q.push(Node(v,dis[v][diss+ds],diss+ds));
            }
        } 
    }
}
int main()
{
    ios::sync_with_stdio(false);
    init();
    cin>>xs>>ys>>xd>>yd>>b>>c0>>t;
    c[0]=c0;
    for(int i=1;i<=t;i++) cin>>c[i];
    cin>>n;
    p[0].first=xs,p[0].second=ys;
    p[n+1].first=xd,p[n+1].second=yd;
    add(0,n+1,0);//起点终点建边 
    add(n+1,0,0);
    for(int i=1;i<=n;i++) 
    {
        cin>>p[i].first>>p[i].second;
        add(0,i,0),add(i,0,0);//起点与车站建边 
        add(n+1,i,0),add(i,n+1,0);//终点与车站建边 
        cin>>l;
        for(int j=1;j<=l;j++)
        {
            int id,m;
            cin>>id>>m;
            add(i,id+1,m);  
            add(id+1,i,m);
        }
    }
    dijkstra();
    int ans=INF;
    for(int i=0;i<=b;i++)
        ans=min(ans,dis[n+1][i]);
    if(ans==INF) cout<<"-1"<<endl;
    else cout<<ans<<endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值