hdu 3440 House Man (差分约束)

来源:互联网 发布:获取所有股票信息 js 编辑:程序博客网 时间:2024/05/16 01:10

题目描述

传送门

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

题解

因为一共要跳N-1次,所有每次跳跃只能到达比当前位置高的第一个。
设两个高度相邻的位置为x,y,那么限制就是s[max(x,y)]s[min(x,y)]<=d
因为每个房子不能在相同的位置,所以s[i+1]1>=s[i]
因为我们连边的时候就保证了是从前向后连边,所以在用spfa跑最短路的时候,需要取最高和最矮的位置中较靠前的位置作为起点。

代码

#include<iostream>#include<cstring>#include<algorithm>#include<cstdio>#include<cmath>#include<queue>#define N 100003#define inf 2147400000using namespace std;int h[N],dis[N],v[N],c[N],nxt[N],point[N],tot;int n,D,pos[N],can[N],cnt[N],T;int cmp(int x,int y){    return h[x]<h[y];}void add(int x,int y,int z){    tot++; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; c[tot]=z;//  cout<<x<<" "<<y<<" "<<z<<endl;}int spfa(int s,int t){    for (int i=1;i<=n;i++) dis[i]=inf;    memset(can,0,sizeof(can));    memset(cnt,0,sizeof(cnt));    cnt[s]=1; can[s]=1; dis[s]=0;    queue<int> p; p.push(s);    while (!p.empty()) {        int now=p.front(); p.pop();        for (int i=point[now];i;i=nxt[i])         if (dis[v[i]]>dis[now]+c[i]) {            dis[v[i]]=dis[now]+c[i];            if (!can[v[i]]) {                can[v[i]]=1;                cnt[v[i]]++;                if (cnt[v[i]]>n) return -1;                p.push(v[i]);             }         }        can[now]=0;    }    return dis[t];}int main(){    freopen("a.in","r",stdin);    scanf("%d",&T);    for (int t=1;t<=T;t++) {        scanf("%d%d",&n,&D); tot=0;        memset(point,0,sizeof(point));        for (int i=1;i<=n;i++) scanf("%d",&h[i]),pos[i]=i;        sort(pos+1,pos+n+1,cmp);        for (int i=2;i<=n;i++) {            int x=pos[i]; int y=pos[i-1];            if(x>y) swap(x,y);            add(x,y,D);        }        for (int i=1;i<n;i++)          add(i+1,i,-1);        //cout<<spfa()<<endl;        printf("Case %d: %d\n",t,spfa(min(pos[1],pos[n]),max(pos[n],pos[1])));    }}
0 0
原创粉丝点击