题目大意:
有个人经常跳房子,但是他必须从低的跳到高的,他有个能力,他能够把房子搬动,但是他搬动房子之后不能破坏原本的序列,现在给出房子高度的序列,并且给出他能跳房子的最大距离,然后让你求最高的房子到最低的房子间最大的距离。
解题思路:
差分约束
代码:
#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 ", cas, spfa(a, b, n)); } return 0; }