思维迪杰斯特拉升维dp—— swerc Gym - 102501A

Posted zsben991126

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了思维迪杰斯特拉升维dp—— swerc Gym - 102501A相关的知识,希望对你有一定的参考价值。

老套路了。。

/*
给定起点(xs,ys),
终点(xd,yd),
最大旅程距离B
汽车的每公里代价C0
其余交通方式数量T<=100 
其余交通方式代价[C1..CT]<=100
车站数量N<=1000
第i个车站的位置(xi,yi),边数li<=100,每条边(j,mj)表示连向第j个车站,交通方式为mj 
可以开车从s到任一车站或目的地,从任一车站开车到目的地,但是车站间不得开车
问在旅程B内的最小代价 

简化:无向图,起点s,终点t,边(u,v,a,b),要求s->t的路径边权b<=B条件下,边权a最小
直接用二维dij算法,d[u][i]表示到点u,边权b=i情况下a的最小值 
*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define N 200005

struct Edge{
    int to,nxt,a,b;
}e[N<<1];
int head[N],tot,s,t;
void add(int u,int v,int b,int a){
    e[tot].to=v;e[tot].a=a;e[tot].b=b;e[tot].nxt=head[u];head[u]=tot++;
}

int sx,sy,dx,dy,x[N],y[N],B,c0,T,c[N],n;
vector<pair<int,int> >G[N];
int calc(int x1,int y1,int x2,int y2){
    return ceil(sqrt(1.0*(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)));
}
void build(){
    memset(head,-1,sizeof head);
    for(int i=1;i<=n;i++){
        for(auto p:G[i]){
            int id=p.first,m=p.second;
            int dis=calc(x[i],y[i],x[id],y[id]);
            add(i,id,dis,dis*c[m]);
            add(id,i,dis,dis*c[m]);        
        }
    }
    s=n+1,t=n+2;
    int dis=calc(sx,sy,dx,dy);
    add(s,t,dis,dis*c0);
    for(int i=1;i<=n;i++){
        dis=calc(sx,sy,x[i],y[i]);
        add(s,i,dis,dis*c0);
        dis=calc(dx,dy,x[i],y[i]);
        add(i,t,dis,dis*c0);
    }
}


struct Node{
    int a,b,id;
    bool operator>(const Node o) const {
        return a>o.a;
    }
};
int vis[1005][105],d[1005][105];
priority_queue<Node,vector<Node>,greater<Node> >pq;
void dij(){
    for(int i=1;i<=n+2;i++)
        for(int j=0;j<=B;j++)d[i][j]=1e9;
    memset(vis,0,sizeof vis);
    pq.push((Node){0,0,s});
    while(pq.size()){
        Node t=pq.top();pq.pop();
        if(vis[t.id][t.b])continue;
        vis[t.id][t.b]=1;
        int u=t.id,b=t.b,a=t.a;
        for(int i=head[u];i!=-1;i=e[i].nxt){
            int v=e[i].to;
            if(e[i].b+b<=B && !vis[v][e[i].b+b] && d[v][e[i].b+b]>a+e[i].a){
                d[v][e[i].b+b]=a+e[i].a;
                pq.push((Node){a+e[i].a,b+e[i].b,v});
            }
        }
    }
}
int main(){
    cin>>sx>>sy>>dx>>dy>>B>>c0>>T;
    for(int i=1;i<=T;i++)cin>>c[i];
    cin>>n;
    for(int i=1;i<=n;i++){
        scanf("%d%d",&x[i],&y[i]);
        int l;scanf("%d",&l);
        while(l--){
            int j,m;
            scanf("%d%d",&j,&m);
            G[i].push_back(make_pair(j+1,m));
        }
    }
    build();
    dij();
    int ans=1e9;
    for(int i=0;i<=B;i++)
        ans=min(ans,d[t][i]);
    if(ans>=1e9)cout<<-1<<
;
    else cout<<ans<<
;
} 

 

以上是关于思维迪杰斯特拉升维dp—— swerc Gym - 102501A的主要内容,如果未能解决你的问题,请参考以下文章

计算几何多边形面积——swerc Gym - 102501F

求多重邻接表的迪杰斯特拉算法

迪杰斯特拉算法为啥不能有负权边

迪杰斯特拉算法的算法思想

建图思维拓扑排序建图+序列自动机——swerc Gym - 102501G 好题

图论——迪杰斯特拉算法和最小生成树