HDU3440(House Man 差分约束简单题)

题目
在这里插入图片描述
题意: 有N个在一条直线上的房子, 每个房子有着不同的高度, 一个超人可以将这些房子左右移动,但不能改变房子之间的相对位置.现在超人要从最矮的房子跳到刚好比他高的房子上面, 且每次跳的房子都要比当前房子要高.那么最后超人肯定会跳到最高的房子上面, 现在给出超人能够跳的最远距离, 问: 如何摆放这些房子, 使得超人能够经过所有的房子跳到最高的房子, 又要使最矮的房子和最高的房子之间的距离最远??

思路:
1.按高度排完序后 高度相邻的两个房子距离不超过D
2.第i+1个房子距离第i个房子>=1

再者就是注意 是小编号连向大编号。 注意求答案的时候1 n 那个是s/t.

#include<bits/stdc++.h> 
#define fnq freopen("input.txt","r",stdin)
using namespace std;
const int N=1e4+5,INF=0x3f3f3f3f;
struct Edge{int to,nex,len;}edge[N];int head[N<<1],tot;
inline void add(int from,int to,int len){edge[++tot]=(Edge){to,head[from],len},head[from]=tot;}
int vis[N],out[N],dis[N];
queue<int>q;
int spfa(int s,int t,int n){
    while(!q.empty()) q.pop();
    for(int i=1;i<=n;++i) vis[i]=out[i]=0,dis[i]=INF;
    dis[s]=0,q.push(s),vis[s]=1;
    int flag=0;
    while(!q.empty()){
        int x=q.front();q.pop(),vis[x]=0;
        if((++out[x])>n) {flag=1;break;}
        for(int i=head[x];i;i=edge[i].nex){
            int y=edge[i].to,l=edge[i].len;
            if(dis[y]>dis[x]+l){
                dis[y]=dis[x]+l;
                if(!vis[y]) {vis[y]=1,q.push(y);};
            }
        }
    }
    return (flag)?-1:dis[t];
}
struct node{int h,id;}a[N];
inline int cmp(node A,node B){return A.h<B.h;}
int main(){
//    fnq;
    int T,cas=0;scanf("%d",&T);
    while(T--){
        int n,D;scanf("%d%d",&n,&D);
        for(int i=1;i<=n;++i) head[i]=0; tot=0;
        for(int i=1;i<=n;++i) scanf("%d",&a[i].h),a[i].id=i;
        sort(a+1,a+n+1,cmp);
        int flag=0;
        for(int i=1;i<n;++i){
            add(i+1,i,-1);
            int u=min(a[i].id,a[i+1].id),v=a[i].id+a[i+1].id-u;
            if(v-u>D) {flag=1;break;}
            add(u,v,D);
        }
        if(flag) {printf("Case %d: -1\n",++cas);continue;}
        int s=min(a[1].id,a[n].id),t=a[1].id+a[n].id-s;
        printf("Case %d: %d\n",++cas,spfa(s,t,n));
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值