题意:
要从高度最低的地方跳到高度最高的地方 每次跳跃的距离小于等于d
每次只能跳到下一个比他高但是和他高度最接近的位置
每个位置都有一个高度值 并且顺序不能换 最低和最高的最远距离。
定义 s [ i ] s[i] s[i]为点 i i i在的位置,这保证了相对位置
可以得到 s [ i ] > s [ i − 1 ] s[i]>s[i-1] s[i]>s[i−1]
然后对于高度差相邻的两个序号 u , v u,v u,v为了保证能跳过去
得到 s [ u ] − s [ v ] < = d s[u]-s[v]<=d s[u]−s[v]<=d
而且这里一定需要 u > v u>v u>v,因为 u u u在序号上大,所以要远一些的
而且最后是从最矮的位置跑最短路还是从最高的位置,也需要用序号大小来判断
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5+10;
const int inf = 1e9;
struct edge{
int to,nxt,w;
}d[maxn]; int head[maxn],cnt=1;
struct point{
int id,h;
bool operator < (const point&tmp ) const{
return h<tmp.h;
}
}a[maxn];
int n,m,s,dis[maxn],vis[maxn],num[maxn];
void add(int u,int v,int w)
{
d[++cnt] = (edge){v,head[u],w},head[u] = cnt;
}
bool spfa(int s)
{
for(int i=1;i<=n;i++) dis[i] = inf, vis[i] = num[i] = 0;
queue<int>q; q.push( s ); dis[s] = 0;
while( !q.empty() )
{
int u = q.front(); q.pop();
vis[u] = 0;
for(int i=head[u];i;i=d[i].nxt )
{
int v = d[i].to;
if( dis[v]>dis[u]+d[i].w )
{
dis[v] = dis[u]+d[i].w;
if( !vis[v] )
{
q.push( v ),vis[v] = 1;
if( ++num[v]==n ) return false;
}
}
}
}
return 1;
}
int main()
{
int t,casenum = 0; cin >> t;
while( t-- )
{
cin >> n >> m;
for(int i=1;i<=n;i++)
{
cin >> a[i].h, a[i].id = i;
if( i>=2 )
add( i,i-1,-1 );
}
sort( a+1,a+1+n );
for(int i=2;i<=n;i++)
{
int u = a[i-1].id, v = a[i].id;
if( u>v ) swap(u,v);
add( u,v,m );
}
int u = a[1].id, v = a[n].id;
if( u>v ) swap(u,v);
cout << "Case " << ++casenum << ": ";
if( spfa(u) )
cout << dis[v] << endl;
else
cout << "-1\n";
cnt = 1;
for(int i=1;i<=n;i++) head[i] = 0;
}
}