hdu3440 House Man(差分约束)

题目链接

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

分析:
为什么我会放上题目翻译呢?因为这道题真的不好理解

因为这个crazy man一共要跳N-1次,因此每一座楼都会到达,每次一定会跳到高度紧接着的那座楼
而且每个房子不能在相同的位置
这样我们就能得到一些关系了:

对于高度相邻的两座楼 i i j s(max(i,j))s(min(i,j))<=Ts(max(i,j))<=s(min(i,j))+T s ( m a x ( i , j ) ) − s ( m i n ( i , j ) ) <= T , s ( m a x ( i , j ) ) <= s ( m i n ( i , j ) ) + T
s(i+1)s(i)>=1s(i)<=s(i+1)1 s ( i + 1 ) − s ( i ) >= 1 , s ( i ) <= s ( i + 1 ) − 1

直接建图即可

Q.

这道题求的是最大值,为什么我们要跑一个最短路

A.

实际上,我们是通过转化,才把原先的问题变成了一道图论
我们由问题的条件得到的不等式就是最短路的形式,与题设无关
所以还是要用最短路求解

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>

using namespace std;

const int INF=1e9;
const int N=1010;
int n,m,dis[N],cnt[N],st[N],tot=0;
bool in[N];
struct po{
    int h,id;
};
po a[N];
struct node{
    int y,nxt,v;
};
node way[N*10];

int cmp(const po &A,const po &B) {return A.h<B.h;}

void add(int u,int w,int z)
{
    tot++;
    way[tot].y=w;way[tot].v=z;way[tot].nxt=st[u];st[u]=tot;
}

int Bellman(int s,int t)
{
    queue<int> Q;
    memset(dis,0x7f,sizeof(dis));
    memset(cnt,0,sizeof(cnt));
    memset(in,0,sizeof(in));

    Q.push(s); in[s]=1; dis[s]=0;

    while (!Q.empty())
    {
        int now=Q.front(); Q.pop();
        in[now]=0;
        for (int i=st[now];i;i=way[i].nxt)
            if (dis[way[i].y]>dis[now]+way[i].v)
            {
                dis[way[i].y]=dis[now]+way[i].v;
                if (!in[way[i].y])
                {
                    in[way[i].y]=1;
                    if (++cnt[way[i].y]>n) return -1;
                    Q.push(way[i].y);
                }
            }
    }
    return dis[t];
}

int main()
{
    int T;
    scanf("%d",&T);
    for (int cas=1;cas<=T;cas++)
    {
        memset(st,0,sizeof(st)); tot=0;
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++) scanf("%d",&a[i].h),a[i].id=i;
        sort(a+1,a+1+n,cmp);
        for (int i=1;i<n;i++)
        {
            int x=a[i].id;
            int y=a[i+1].id;
            if (x>y) swap(x,y);
            add(x,y,m);

            add(i+1,i,-1);
        }
        printf("Case %d: %d\n",cas,Bellman(min(a[1].id,a[n].id),max(a[1].id,a[n].id)));
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值