HDU 3440 House Man (contrainte différentielle)

Question: Il y a N maisons sur une ligne droite. Chaque maison a une hauteur différente. Superman peut déplacer ces maisons à gauche et à droite, mais ne peut pas changer la position relative entre les maisons. Superman veut sauter de la maison la plus courte à une maison juste plus haute que lui, et chaque fois qu'il saute une maison plus haute que la maison actuelle, il doit sauter N-1 fois. Ensuite, à la fin, Superman sautera définitivement vers la maison la plus haute. Maintenant, donnez la plus longue distance D que Superman puisse sauter à la fois. Comment organiser ces maisons pour que Superman puisse sauter à travers toutes les maisons jusqu'à la maison la plus haute, et en faire la plus courte La distance entre la maison et la maison la plus haute est la plus éloignée et la sortie est la plus éloignée.

Solution du problème: contrainte de différence.
Trouvez la distance la plus longue et exécutez le chemin le plus court. Nous utilisons d [i] d [i]d [ i ] représente la distance depuis le point de départ.

Comme l'ordre inhérent à la maison n'est pas modifié, l'équation de contrainte peut être obtenue:
d [i - 1] - d [i] <= - 1 d [i-1] -d [i] <= - 1d [ i-1 ]-d [ i ]<=- 1

Considérons ensuite l'ordre de saut, car la distance entre les deux maisons ne peut pas dépasser D, nous pouvons définir des contraintes en fonction de la taille de l'id après le tri.

En même temps, la taille de l'identifiant du point de départ et du point de fin doit également être prise en compte. Le résultat final étant positif, l'identifiant du point de départ doit être plus petit que le point final, qu'il passe de bas en haut ou de haut en bas.

#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;
}

Je suppose que tu aimes

Origine blog.csdn.net/qq_43680965/article/details/108757913
conseillé
Classement