HDU 3440 House Man

题意:在水平坐标上有N个不同高度的房子,有个人他练习跳跃,他从最矮到高跳跃房子,他每次跳跃的水平距离不超过d。他可以水平移动每座房子,但每座房子不能在一个点,房子坐落的点都是正数点。问最矮的房子离最高的房子最大距离。

解:

差分约束系统,由于人只能从矮的房子跳到高的房子,并且水平跳跃距离最大为的,设此时坐标为Xi,下次跳跃点坐标为Xj的坐标,|Xi-Xj|<=d

由于存在绝对值,不等式就变复杂了,建图也复杂。所以,我们规定大的坐标减小的坐标,打开绝对值符号。

得到N-1个不等式,还有个隐藏条件是相邻的房子坐标差值大于1 ,由于求的答案要最大,因此所有的不等式符号为<=,我们把大于号转化为小于号有得到一个不等式组,通过不等式组建图。

最后要求ph-pl<=?,即最低点到最高点的最大距离。如果ph坐标小于pl,因为之前规定了小坐标指向大坐标,那么转换为pl-ph<=?。

要求最矮的房子离最高的房子最大距离。我们以最矮房子为原点跑最短路(spfa),得到最后的结果。如果SPFA中,某点进入队列超过N次,则无解。

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <string.h>
#include <map>
#include <set>
using namespace std;
#define MAXN 1005
#define LL long long
#define INF 0x3f7f7f7f
int n,d;
struct point
{
    int id,high;
    point(int id=0,int high=0):id(id),high(high){}
    friend bool operator<(point x,point y)
    {
        return x.high<y.high;
    }
};
struct point po[MAXN];
struct node
{
    int en,len,next;
}Edge[MAXN*MAXN];
int p[MAXN],num;
int dis[MAXN],vis[MAXN],cnt[MAXN];
void init()
{
    memset(p,-1,sizeof(p));
    num=0;
}
void add(int st,int en,int len)
{
    Edge[num].en=en;
    Edge[num].len=len;
    Edge[num].next=p[st];
    p[st]=num++;
}
void spfa(int st,int en)
{
    int i;
    for(i=1;i<=n;i++)
    {
        dis[i]=INF;
        vis[i]=0;
        cnt[i]=0;
    }
    dis[st]=0;
    queue<int>q;
    q.push(st);
    cnt[st]=1;
    vis[st]=1;
    while(!q.empty())
    {
        int tx=q.front();
        q.pop();
        vis[tx]=0;
        for(i=p[tx];i!=-1;i=Edge[i].next)
        {
            int v=Edge[i].en;
            int len=Edge[i].len;
            if(dis[v]>dis[tx]+len)
            {
                dis[v]=dis[tx]+len;
                if(!vis[v])
                {
                    vis[v]=1;
                    cnt[v]++;
                    if(cnt[v]>n){puts("-1");return ;}//无解
                    q.push(v);
                }
            }
        }
    }
    if(dis[en]==INF)puts("-1");
    else printf("%d\n",dis[en]);
}
int main()
{

    int i;
    int t,cas;
    scanf("%d",&t);
    for(cas=1;cas<=t;cas++)
    {
        init();
        scanf("%d%d",&n,&d);
        for(i=1;i<=n;i++)
        {
            scanf("%d",&po[i].high);
            po[i].id=i;
        }
        sort(po+1,po+1+n);//按高度排序
        for(i=2;i<=n;i++)
        {
            if(po[i].id<po[i-1].id)
            add(po[i].id,po[i-1].id,d);//建图
            else add(po[i-1].id,po[i].id,d);
        }
        for(i=1;i<n;i++)
        {
            add(i+1,i,-1);//相邻点建图
        }
        printf("Case %d: ",cas);
        spfa(min(po[1].id,po[n].id),max(po[1].id,po[n].id));/

    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值