hdu 3440(差分约束系统)

hdu 3440

(1)题意:

一个人从高度较低的房子跳到高度较高的房子,他可以跳跃的水平最远距离为D,

他只能从左向右跳,房子的编号是从1~n,从左向右编号。

两个房子之间只要水平距离小于D,并且房子A的高度小于B的高度就能从房子A跳到房子B。

他可以任意调整所有房子之间的相对距离,两个房子之间的最小距离是1,

求他要从最低的房子跳到最高的房子并且跳过所有的房子,需要的最短的距离(保证所有的房子的高度不一样)。

(2)思路:

每个房子调整后的距离一定是di+1-di>=1,并且要保证每次能从较低的房子A跳到较高的房子B,

并且AB之间的距离小于等于D。

所以先将所有的编号按照高度大小从小到大排序,

要确定两个房子之间能都跳到,并且从左向右跳,一定是从编号较小的位置跳到编号较大的位置,

所以从dmi-dmx<=di.

(3)代码:

参考文章

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn = 1024;
const int INF = 2e9+10;
int vis[maxn],dis[maxn],head[maxn],tot,n,bh[maxn],hi[maxn];
struct Node{
	int v,nxt,w;
}cur[maxn<<2];
int MIN(int x,int y){
	return x<y?x:y;
}
int MAX(int x,int y){
	return x>y?x:y;
}
bool cmp(int x,int y){
	return hi[x]<hi[y];
}
void Init(){
	memset(head,-1,sizeof(head));
	tot = 0;
}
void Add(int x,int y,int z){
	cur[tot] = Node{y,head[x],z};
	head[x] = tot++;
}
int spfa(int st,int ed){
	for(int i=0;i<=n;i++){
		vis[i] = 0;dis[i] = INF;
	}
	dis[st] = 0;
	queue <int> q;
	q.push(st);
	while(!q.empty()){
		int x = q.front();q.pop();vis[x] = 0;//printf("x = %d\n",x);
		for(int i=head[x];i!=-1;i=cur[i].nxt){
			int y = cur[i].v;//printf("y = %d w = %d,",y,cur[i].w);
			if(dis[y]>dis[x]+cur[i].w){
				dis[y] = dis[x]+cur[i].w;
				if(vis[y]==0){
					vis[y] = 1;
					q.push(y);
				}
			}
		}
		//printf("\n");
	}
	return dis[ed]==INF?-1:dis[ed];
}
int main(void){
	int T,pt = 1;
	scanf("%d",&T);
	while(T--){
		Init(); int d;
		scanf("%d%d",&n,&d);
		for(int i=1;i<=n;i++){
			scanf("%d",&hi[i]);bh[i] = i;
		}
		sort(bh+1,bh+n+1,cmp);
		int fg = 0;
		for(int i=1;i<n;i++){
			Add(i+1,i,-1);
			int x = MIN(bh[i],bh[i+1]),y = MAX(bh[i],bh[i+1]);
			if(y-x>d){
				fg = 1;break;
			}
			else Add(x,y,d);
		}
		
		int st = MIN(bh[1],bh[n]),ed = MAX(bh[1],bh[n]);
		int ans = spfa(st,ed);
		if(ans==INF) fg = 1;
		printf("Case %d: %d\n",pt++,(fg==1?-1:ans));
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41829060/article/details/91561958
今日推荐