题目大意:
有个人经常跳房子,但是他必须从低的跳到高的,他有个能力,他能够把房子搬动,但是他搬动房子之后不能破坏原本的序列,现在给出房子高度的序列,并且给出他能跳房子的最大距离,然后让你求最高的房子到最低的房子间最大的距离。
解题思路:
差分约束
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 1000 + 5;
const int INF = 0x7fffffff;
typedef struct point{
int h, index;
point(int a = 0, int b = 0){
h = a; index = b;
}
bool operator < (point a){
return h < a.h;
}
}P;
typedef struct node{
int to, w;
int next;
node(int a = 0, int b = 0, int c = 0){
to = a; w = b; next = c;
}
}Edge;
P p[maxn];
Edge edge[maxn * maxn];
int tot, Stack[maxn], h[maxn];
int head[maxn * maxn], dis[maxn], vis[maxn], cnt[maxn];
inline int Max(int a, int b){
return (a >= b ? a : b);
}
inline int Min(int a, int b){
return (a <= b ? a : b);
}
inline void add(int u, int v, int w){
edge[tot] = Edge(v, w, head[u]);
head[u] = tot++;
}
int spfa(int s, int e, int n){
int u, v, top = 0;
for(int i = 0; i <= n; ++i){
dis[i] = INF;
vis[i] = 0; cnt[i] = 0;
}
Stack[top++] = s; dis[s] = 0; vis[s] = 1;
while(top){
u = Stack[--top]; vis[u] = 0;
if((++cnt[u]) > n) return -1;
for(int i = head[u]; ~i; i = edge[i].next){
v = edge[i].to;
if(dis[v] > dis[u] + edge[i].w){
dis[v] = dis[u] + edge[i].w;
if(!vis[v]){
vis[v] = 1;
Stack[top++] = v;
}
}
}
}
return dis[e];
}
int main(){
int t, n, a, b, d;
scanf("%d", &t);
for(int cas = 1; cas <= t; ++cas){
tot = 0;
memset(head, -1, sizeof(head));
scanf("%d%d", &n, &d);
for(int i = 1; i <= n; ++i){
scanf("%d", &h[i]);
p[i] = P(h[i], i);
}
sort(p + 1, p + 1 + n);
for(int i = 1; i < n; ++i){
a = Max(p[i].index, p[i+1].index);
b = Min(p[i].index, p[i+1].index);
add(i, i + 1, -1);
add(a, b, d);
}
a = Max(p[n].index, p[1].index);
b = Min(p[n].index, p[1].index);
printf("Case %d: %d\n", cas, spfa(a, b, n));
}
return 0;
}