HDU 3440 House Man (differential constraint)

Question: There are N houses on a straight line. Each house has a different height. Superman can move these houses left and right, but cannot change the relative position between the houses. Superman wants to jump from the shortest house to a house just taller than him, and every time he jumps a house higher than the current house, he has to jump N-1 times. Then in the end Superman will definitely jump to the tallest house. Now give the longest distance D that Superman can jump at a time. How to arrange these houses so that Superman can jump through all the houses to the tallest house, and make it the shortest The distance between the house and the tallest house is the furthest, and the output is the furthest.

Problem solution: difference constraint.
Find the longest distance and run the shortest path. We use d [i] d[i]d [ i ] represents the distance from the starting point.

Since the inherent order of the house is not changed, the constraint equation can be obtained:
d [i − 1] − d [i] <= − 1 d[i-1]-d[i]<=-1d[i1]d[i]<=1

Then consider the order of jumping, because the distance between the two houses cannot exceed D, we can set constraints based on the id size after sorting.

At the same time, the id size of the starting point and the ending point should also be considered. Because the final result is positive, the id of the starting point should be smaller than the end point, regardless of whether it jumps from low to high or high to low.

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<fstream>
#include<set>
#include<map>
#include<sstream>
#include<iomanip>
#define ll long long
#define pii pair<int, int>
using namespace std;
const int maxn = 1e3 + 5;
int t, n, D;
struct node1 {
    
    
	int h, id;
	bool operator<(const node1 x)const {
    
    
		return h < x.h;
	}
}h[maxn];
struct node {
    
    
	int v, nxt, w;
}edge[maxn << 2];
int vis[maxn], d[maxn], head[maxn], mark[maxn], k, s;
void add(int u, int v, int w) {
    
    
	edge[++k].nxt = head[u];
	edge[k].v = v;
	edge[k].w = w;
	head[u] = k;
}
bool spfa() {
    
    
	for (int i = 1; i <= n; i++) {
    
    
		vis[i] = mark[i] = 0;
		d[i] = 0x3f3f3f3f;
	}
	queue<int>q;
	q.push(s);
	mark[s] = vis[s] = 1;
	d[s] = 0;
	while (!q.empty()) {
    
    
		int u = q.front(); q.pop();
		vis[u] = 0;
		for (int i = head[u]; i; i = edge[i].nxt) {
    
    
			int v = edge[i].v, w = edge[i].w;
			if (d[v] > d[u] + w) {
    
    
				d[v] = d[u] + w;
				if (vis[v]) continue;
				vis[v] = 1;
				if(++mark[v] > n) return false;  //负环 n+1以上才有负环
				q.push(v);
			}
		}
	}
	return true;
}

int main() {
    
    
	int cas = 0;
	scanf("%d", &t);
	while (t--) {
    
    
		k = 0;
		memset(head, 0, sizeof(head));
		scanf("%d%d", &n, &D);
		for (int i = 1; i <= n; i++) {
    
    
			scanf("%d", &h[i].h);
			h[i].id = i;
			if (i != 1) add(i, i - 1, -1);
		}
		sort(h + 1, h + n + 1);
		for (int i = 2; i <= n; i++) {
    
    
			if (h[i].id > h[i - 1].id) add(h[i - 1].id, h[i].id, D);
			else add(h[i].id, h[i - 1].id, D);
		}
		s = min(h[1].id, h[n].id);
		if (spfa()) printf("Case %d: %d\n", ++cas, d[max(h[1].id, h[n].id)]);
		else printf("Case %d: %d\n", ++cas, -1);
	}
	return 0;
}

Guess you like

Origin blog.csdn.net/qq_43680965/article/details/108757913