题目
题意: 有N个在一条直线上的房子, 每个房子有着不同的高度, 一个超人可以将这些房子左右移动,但不能改变房子之间的相对位置.现在超人要从最矮的房子跳到刚好比他高的房子上面, 且每次跳的房子都要比当前房子要高.那么最后超人肯定会跳到最高的房子上面, 现在给出超人能够跳的最远距离, 问: 如何摆放这些房子, 使得超人能够经过所有的房子跳到最高的房子, 又要使最矮的房子和最高的房子之间的距离最远??
思路:
1.按高度排完序后 高度相邻的两个房子距离不超过D
2.第i+1个房子距离第i个房子>=1
再者就是注意 是小编号连向大编号。 注意求答案的时候1 n 那个是s/t.
#include<bits/stdc++.h>
#define fnq freopen("input.txt","r",stdin)
using namespace std;
const int N=1e4+5,INF=0x3f3f3f3f;
struct Edge{int to,nex,len;}edge[N];int head[N<<1],tot;
inline void add(int from,int to,int len){edge[++tot]=(Edge){to,head[from],len},head[from]=tot;}
int vis[N],out[N],dis[N];
queue<int>q;
int spfa(int s,int t,int n){
while(!q.empty()) q.pop();
for(int i=1;i<=n;++i) vis[i]=out[i]=0,dis[i]=INF;
dis[s]=0,q.push(s),vis[s]=1;
int flag=0;
while(!q.empty()){
int x=q.front();q.pop(),vis[x]=0;
if((++out[x])>n) {flag=1;break;}
for(int i=head[x];i;i=edge[i].nex){
int y=edge[i].to,l=edge[i].len;
if(dis[y]>dis[x]+l){
dis[y]=dis[x]+l;
if(!vis[y]) {vis[y]=1,q.push(y);};
}
}
}
return (flag)?-1:dis[t];
}
struct node{int h,id;}a[N];
inline int cmp(node A,node B){return A.h<B.h;}
int main(){
// fnq;
int T,cas=0;scanf("%d",&T);
while(T--){
int n,D;scanf("%d%d",&n,&D);
for(int i=1;i<=n;++i) head[i]=0; tot=0;
for(int i=1;i<=n;++i) scanf("%d",&a[i].h),a[i].id=i;
sort(a+1,a+n+1,cmp);
int flag=0;
for(int i=1;i<n;++i){
add(i+1,i,-1);
int u=min(a[i].id,a[i+1].id),v=a[i].id+a[i+1].id-u;
if(v-u>D) {flag=1;break;}
add(u,v,D);
}
if(flag) {printf("Case %d: -1\n",++cas);continue;}
int s=min(a[1].id,a[n].id),t=a[1].id+a[n].id-s;
printf("Case %d: %d\n",++cas,spfa(s,t,n));
}
}