hdu 3440 House Man

https://vjudge.net/problem/HDU-3440

题意:

一个超人,他可以一个从一栋楼跳到另一栋楼。有一天,他为了加强技能,准备跳一系列的楼,他每次都从低的楼,跳到高的楼。他从最低的楼开始跳,但是他跳的水平距离是有限制的。

但是因为他是超人,所以他可以任意移动楼,而且他想他开始跳的楼与最后跳到的楼的距离最大。

他移动楼的时候有某些限制:

1.移动之后的楼的排列顺序必须与输入的顺序相同。

2.必须满足水平跳跃的距离的限制。

求这个最大距离,如果跳不到的话,输出-1。

思路:

首先,超人跳的每栋楼的是按照高度递增的顺序来的,比如说i,j是高度相邻的两栋楼,那么两栋楼之间的距离肯定得满足|xi - xj| <= d(限制),然后因为每栋楼之间的距离肯定是大于等于1的,所以Xi+1 - Xi >= 1,所以我们就可以找出一系列的不等式。我们需要通过这一系列的不等式找出加入最低的下标为u,最高的下标为v,那么就是|Xu-Xv|的最大值,这样的问题其实是一类叫做差分约束系统的问题。

差分约束系统是由最短路的松弛条件d[v] >= d[u] + w(u,v) 得来的,假设有不等式 Xi - Xj <= len,变形得到 Xi <= Xj + len,这样就和最短路的松弛条件近似了,虽然说一个是大于等于,一个是小于等于,但是本质其实是一样的,可以看成d[i] <= d[j] + w(j,i),那么此时就可以建一条从j到i的边,然后求出目标不等式的最大值,即相当于求图中的最短路。

为什么是最短路呢?比如有a - b <= 3 ,b - c <= 5,a - c <= 10,此时如果要求a - c的最大值,可以轻易地看出最大值是8,即是图中的a到c的最短路,而不是10,本质是求所有不等式的交集,按照差分的约束条件 <= ,那么就是求最小的那个。

还剩一个问题就是有没有可能出现无解的情况,那就是图中出现了负环,最短路可以无穷小,此时当然就无解了,比如b - a <= -3,c - b <= 2 ,a - c <= -5,那么此时就是一个负环,此时求c - a的最小值,有c - a <= -1,c - a >= 5,此时就矛盾了,不存在最小值。

ok,回过来看这道题,根据题中的|xi - xj| <= d,我们可以建图,去掉绝对值的方法就是边从下标小的点指向下标大的点,因为输入的楼之间是有先后顺序的,之后因为每栋楼之间的距离必须大于等于1,所以Xi+1 - Xi >= 1(上面提到了,之后跑图的话,就用spfa,因为dij无法判断途中是否存在负环,spfa判断途中是否存在负环的条件是一个点入队的次数大于了n。

代码:

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <vector>
  4 #include <queue>
  5 #include <algorithm>
  6 using namespace std;
  7
  8 struct edge
  9 {
 10     int from,to;
 11     int w;
 12
 13     edge(){};
 14     edge(int x,int y,int z)
 15     {
 16         from = x;
 17         to = y;
 18         w = z;
 19     }
 20 };
 21
 22 struct node
 23 {
 24     int hei;
 25     int id;
 26
 27     bool operator < (const node &rhs) const
 28     {
 29         return this -> hei < rhs.hei;
 30     }
 31 } h[1005];
 32
 33 vector<edge> edges;
 34 vector<int> v[1005];
 35
 36 void init(int n)
 37 {
 38     edges.clear();
 39
 40     for (int i = 0;i <= n;i++)
 41         v[i].clear();
 42 }
 43
 44 void adde(int from,int to,int w)
 45 {
 46     edge e = edge(from,to,w);
 47
 48     edges.push_back(e);
 49
 50     int sz = edges.size();
 51
 52     v[from].push_back(sz - 1);
 53 }
 54
 55 bool vis[1005];
 56 int d[1005];
 57 int cnt[1005];
 58 const int inf = 0x3f3f3f3f;
 59
 60 bool spfa(int s,int n)
 61 {
 62     memset(vis,0,sizeof(vis));
 63     memset(d,inf,sizeof(d));
 64     memset(cnt,0,sizeof(cnt));
 65
 66     vis[s] = 1;
 67     cnt[s] = 1;
 68
 69     queue<int> q;
 70
 71     q.push(s);
 72
 73     d[s] = 0;
 74
 75     while (!q.empty())
 76     {
 77         int cur = q.front();
 78         q.pop();
 79
 80         vis[cur] = 0;
 81
 82         for (int i = 0;i < v[cur].size();i++)
 83         {
 84             int id = v[cur][i];
 85
 86             int to = edges[id].to;
 87
 88             if (d[to] > d[cur] + edges[id].w)
 89             {
 90                 d[to] = d[cur] + edges[id].w;
 91
 92                 if (!vis[to])
 93                 {
 94                     q.push(to);
 95                     vis[to] = 1;
 96                     cnt[to]++;
 97
 98                     if (cnt[to] > n) return 1;
 99                 }
100             }
101         }
102     }
103
104     return 0;
105 }
106
107 int main()
108 {
109     int t;
110     int cas = 0;
111
112     scanf("%d",&t);
113
114     while (t--)
115     {
116         printf("Case %d: ",++cas);
117
118         int n,dis;
119
120         scanf("%d%d",&n,&dis);
121
122         init(n);
123
124         for (int i = 1;i <= n;i++)
125         {
126             scanf("%d",&h[i].hei);
127             h[i].id = i;
128         }
129
130         for (int i = 1;i < n;i++)
131         {
132             adde(i+1,i,-1);
133         }
134
135         sort(h+1,h+n+1);
136
137         for (int i = 1;i < n;i++)
138         {
139             int x = min(h[i].id,h[i+1].id);
140             int y = max(h[i].id,h[i+1].id);
141             adde(x,y,dis);
142         }
143
144         int s = min(h[1].id,h[n].id);
145         int en = max(h[1].id,h[n].id);
146
147         bool f = spfa(s,n);
148
149         if (f) printf("-1\n");
150         else printf("%d\n",d[en]);
151     }
152
153     return 0;
154 }
时间: 2024-12-15 07:14:43

hdu 3440 House Man的相关文章

HDU 3440 查分约束

点击打开链接 题意:给个n个不同的高度,一个人从最低点跳跃,每次可以跳到第一个比它高的位置,最后跳到最高点,然后每次最多可以跳的距离为D,而且在跳跃时可以在不改变给定顺序的情况下移动这些高度,使得最后起始点和终点的位置最远, 思路:自己想了一会,想的方向错了,我自己想的方法是将最小高度记为0,最大高度记为n-1,然后写查分约束方程,这了一会发现条件不足,没想法了,看了大牛们的解法发现原来以给定的顺序直接进行条件就可以了,而且好简单,因为我们不能调整给定的顺序,那么对于给定的顺序就可以有pos(i

hdu 3440 Housu Man 差分约束系统

题意:有n个屋子,超人从最矮的屋子开始,依次跳下比当前屋子高且最接近当前高度的屋子(即按照屋子高度增序来跳),但超人跳跃还有一个水平距离限制D,他每次跳的水平距离<=D.现在给你每个屋子的高度是它们的相对位置,你不能改变屋子的相对位置,但是可以水平移动屋子,使得最矮的屋子和最高的屋子的水平距离最大.如果无论怎样移动,超人都无法跳到最后那个屋子则输出-1 分析:这题是个差分约束系统 首先得明白这题是要求最大值,那么就把每个不等式都转换成x-y<=k的形式,然后连一条y->x权值为k的边.

差分约束(例题整理)

例题一:HDU 3440  样例输入: 3 4 4 20 30 10 40 5 6 20 34 54 10 15 4 2 10 20 16 13 样例输出: Case 1: 3 Case 2: 3 Case 3: -1 1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<queue> 5 #include<cstring> 6 #include<cstdl

图论 500题——主要为hdu/poj/zoj

转自——http://blog.csdn.net/qwe20060514/article/details/8112550 =============================以下是最小生成树+并查集======================================[HDU]1213   How Many Tables   基础并查集★1272   小希的迷宫   基础并查集★1325&&poj1308  Is It A Tree?   基础并查集★1856   More i

hdu图论题目分类

=============================以下是最小生成树+并查集====================================== [HDU] 1213 How Many Tables 基础并查集★ 1272 小希的迷宫 基础并查集★ 1325&&poj1308 Is It A Tree? 基础并查集★ 1856 More is better 基础并查集★ 1102 Constructing Roads 基础最小生成树★ 1232 畅通工程 基础并查集★ 123

hdu 差分约束题集

[HDU]1384 Intervals 基础差分约束★1529 Cashier Employment 神级差分约束★★★★ 1531 King 差分约束★1534 Schedule Problem 差分约束输出一组解★3440 House Man 比较好的差分约束★★3592 World Exhibition 简单★3666 THE MATRIX PROBLEM 中等★★4274 Spy's Work [先处理出欧拉序列,然后就是差分约束了...] [POJ]1201 Intervals1275

HDU 6203 ping ping ping [LCA,贪心,DFS序,BIT(树状数组)]

题目链接:[http://acm.hdu.edu.cn/showproblem.php?pid=6203] 题意 :给出一棵树,如果(a,b)路径上有坏点,那么(a,b)之间不联通,给出一些不联通的点对,然后判断最少有多少个坏点. 题解 :求每个点对的LCA,然后根据LCA的深度排序.从LCA最深的点对开始,如果a或者b点已经有点被标记了,那么continue,否者标记(a,b)LCA的子树每个顶点加1. #include<Bits/stdc++.h> using namespace std;

HDU 5542 The Battle of Chibi dp+树状数组

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5542 题意:给你n个数,求其中上升子序列长度为m的个数 可以考虑用dp[i][j]表示以a[i]结尾的长度为j的上升子序列有多少 裸的dp是o(n2m) 所以需要优化 我们可以发现dp的第3维是找比它小的数,那么就可以用树状数组来找 这样就可以降低复杂度 #include<iostream> #include<cstdio> #include<cstring> #include

hdu 1207 汉诺塔II (DP+递推)

汉诺塔II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4529    Accepted Submission(s): 2231 Problem Description 经典的汉诺塔问题经常作为一个递归的经典例题存在.可能有人并不知道汉诺塔问题的典故.汉诺塔来源于印度传说的一个故事,上帝创造世界时作了三根金刚石柱子,在一根柱子上从下往