思维迪杰斯特拉升维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