本文主要是介绍【CF】1422D-Returning Home 题解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
传送门:1422D
标签:贪心
题目大意
Yura 已经走了很长时间,他计划尽快回家。为了做到这一点,Yura 可以利用城市周围的瞬间移动地点。把城市看作是一个 n × n n × n n×n 方形街区。Yura 需要从坐标 ( s x , s y ) (s_x, s_y) (sx,sy) 的街区移动到坐标 ( f x , f y ) (f_x, f_y) (fx,fy) 的街区。在一分钟内,Yura 可以移动到相邻的街区;换句话说,他可以在四个方向上移动。此外,城市中有 m m m 个瞬间移动地点。他们的坐标已知并告诉 Yura。如果 Yura 所在的街区与瞬间移动地点的坐标相同,他可以在不花费时间的情况下移动到瞬间移动地点。帮助 Yura 找出回家所需的最短时间。
输入:第一行包含两个整数 n n n 和 m m m — 城市的大小和瞬间移动地点的数量( 1 ≤ n ≤ 1 0 9 1 ≤ n ≤ 10^9 1≤n≤109, 0 ≤ m ≤ 1 0 5 0 ≤ m ≤ 10^5 0≤m≤105)。下一行包含四个整数 s x , s y , f x , f y s_x, s_y, f_x, f_y sx,sy,fx,fy — Yura 的初始位置坐标和他的家的坐标( 1 ≤ s x , s y , f x , f y ≤ n 1 ≤ s_x, s_y, f_x, f_y ≤ n 1≤sx,sy,fx,fy≤n)。接下来的 m m m 行各包含两个整数 x i , y i x_i, y_i xi,yi — 第 i i i 个瞬间移动地点的坐标( 1 ≤ x i , y i ≤ n 1 ≤ x_i, y_i ≤ n 1≤xi,yi≤n)。
输出:在唯一行中输出返回所需的时间。
算法分析
很显然,当 K = 2 K = 2 K=2 时,我们可以从任何原子 i i i( 1 ≤ i < N 1 ≤ i < N 1≤i<N)开始制作激发路线来激发所有原子。因此,对于 K > 2 K > 2 K>2,我们可以通过切换键来制作路线。因此,有三种情况:
如果 K = 0 K = 0 K=0,最优选择是只激发一个原子。尝试激发每个原子 i i i 并使用前缀和计算获得的能量。
如果 K ≥ 2 K ≥ 2 K≥2,我们可以选择激发一个原子 i i i( 1 ≤ i < N 1 ≤ i < N 1≤i<N),这会激发所有原子,或者仅激发最后一个原子(如果 D D D 最低的话)。
如果 K = 1 K = 1 K=1 ,需要分情况讨论,共有五种情况:
- 将 E N − 1 E_{N - 1} EN−1 改变为 1。然后激发 D i D_i Di 在 1 ≤ i < N 1 ≤ i < N 1≤i<N 的原子。同时,如果能量增加,则激发原子 N N N。
- 将 E i E_i Ei 改变为 1 然后激发原子 i i i 和 i + 1 i + 1 i+1( 1 < i < N 1 < i < N 1<i<N)。激发 i + 1 i + 1 i+1 是最优的,因为如果不这样做,情况会比情况 1 更糟。
- 将 E 1 E_1 E1 改变为 3,然后激发 1 和 2。
- 将 E 1 E_1 E1 改变为 N N N,然后激发原子 i i i( 1 < i ≤ N 1 < i ≤ N 1<i≤N)
- 将 E i E_i Ei 改变为 i + 2 i + 2 i+2,然后激发原子 1( 1 < i < N 1 < i < N 1<i<N)。只有当我们激发原子 1 时,这是最优的,否则它比情况 4 更差。
总体时间复杂度: O ( N ) O(N) O(N)
代码实现
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=3e6+10;
struct node
{int x,y,id;
}f[N];
struct node1
{int to,w,next;
}e[N];
int cnt,head[N];
int dist[N],vis[N];
int n,m;
void add(int x,int y,int z)
{cnt++;e[cnt].to=y;e[cnt].w=z;e[cnt].next=head[x];head[x]=cnt;
}
bool cmp1(node a,node b)
{return a.x<b.x;
}
bool cmp2(node a,node b)
{return a.y<b.y;
}
void dij()
{memset(dist,0x3f,sizeof dist);dist[m+1]=0;priority_queue<pair<int,int> > q;q.push({0,m+1});while(q.size()){auto p=q.top();q.pop();int xx=p.second;if(vis[xx]) continue;vis[xx]=1;for(int i=head[xx];i;i=e[i].next){int yy=e[i].to;if(dist[yy]>dist[xx]+e[i].w){dist[yy]=dist[xx]+e[i].w;q.push({-dist[yy],yy});}}}
}
signed main()
{cin>>n>>m;int sx,sy,ex,ey;cin>>sx>>sy>>ex>>ey;for(int i=1;i<=m;i++){int x,y;cin>>x>>y;f[i].x=x,f[i].y=y,f[i].id=i;add(m+1,i,min(abs(x-sx),abs(y-sy)));add(i,m+1,min(abs(x-sx),abs(y-sy)));add(m+2,i,abs(x-ex)+abs(y-ey));add(i,m+2,abs(x-ex)+abs(y-ey));}add(m+1,m+2,abs(sx-ex)+abs(sy-ey));add(m+2,m+1,abs(sx-ex)+abs(sy-ey));sort(f+1,f+m+1,cmp1);for(int i=2;i<=m;i++){int id1=f[i-1].id,id2=f[i].id;int w=min(abs(f[i].x-f[i-1].x),abs(f[i].y-f[i-1].y));add(id1,id2,w);add(id2,id1,w);}sort(f+1,f+m+1,cmp2);for(int i=2;i<=m;i++){int id1=f[i-1].id,id2=f[i].id;int w=min(abs(f[i].x-f[i-1].x),abs(f[i].y-f[i-1].y));add(id1,id2,w);add(id2,id1,w);}dij();cout<<dist[m+2]<<'\n';
}
这篇关于【CF】1422D-Returning Home 题解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!