(1)题意:
一个人从高度较低的房子跳到高度较高的房子,他可以跳跃的水平最远距离为D,
他只能从左向右跳,房子的编号是从1~n,从左向右编号。
两个房子之间只要水平距离小于D,并且房子A的高度小于B的高度就能从房子A跳到房子B。
他可以任意调整所有房子之间的相对距离,两个房子之间的最小距离是1,
求他要从最低的房子跳到最高的房子并且跳过所有的房子,需要的最短的距离(保证所有的房子的高度不一样)。
(2)思路:
每个房子调整后的距离一定是di+1-di>=1,并且要保证每次能从较低的房子A跳到较高的房子B,
并且AB之间的距离小于等于D。
所以先将所有的编号按照高度大小从小到大排序,
要确定两个房子之间能都跳到,并且从左向右跳,一定是从编号较小的位置跳到编号较大的位置,
所以从dmi-dmx<=di.
(3)代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn = 1024;
const int INF = 2e9+10;
int vis[maxn],dis[maxn],head[maxn],tot,n,bh[maxn],hi[maxn];
struct Node{
int v,nxt,w;
}cur[maxn<<2];
int MIN(int x,int y){
return x<y?x:y;
}
int MAX(int x,int y){
return x>y?x:y;
}
bool cmp(int x,int y){
return hi[x]<hi[y];
}
void Init(){
memset(head,-1,sizeof(head));
tot = 0;
}
void Add(int x,int y,int z){
cur[tot] = Node{y,head[x],z};
head[x] = tot++;
}
int spfa(int st,int ed){
for(int i=0;i<=n;i++){
vis[i] = 0;dis[i] = INF;
}
dis[st] = 0;
queue <int> q;
q.push(st);
while(!q.empty()){
int x = q.front();q.pop();vis[x] = 0;//printf("x = %d\n",x);
for(int i=head[x];i!=-1;i=cur[i].nxt){
int y = cur[i].v;//printf("y = %d w = %d,",y,cur[i].w);
if(dis[y]>dis[x]+cur[i].w){
dis[y] = dis[x]+cur[i].w;
if(vis[y]==0){
vis[y] = 1;
q.push(y);
}
}
}
//printf("\n");
}
return dis[ed]==INF?-1:dis[ed];
}
int main(void){
int T,pt = 1;
scanf("%d",&T);
while(T--){
Init(); int d;
scanf("%d%d",&n,&d);
for(int i=1;i<=n;i++){
scanf("%d",&hi[i]);bh[i] = i;
}
sort(bh+1,bh+n+1,cmp);
int fg = 0;
for(int i=1;i<n;i++){
Add(i+1,i,-1);
int x = MIN(bh[i],bh[i+1]),y = MAX(bh[i],bh[i+1]);
if(y-x>d){
fg = 1;break;
}
else Add(x,y,d);
}
int st = MIN(bh[1],bh[n]),ed = MAX(bh[1],bh[n]);
int ans = spfa(st,ed);
if(ans==INF) fg = 1;
printf("Case %d: %d\n",pt++,(fg==1?-1:ans));
}
return 0;
}