1. 程式人生 > >hdu 3440 House Man

hdu 3440 House Man

tdi 大於等於 clear printf push_back 等於 node const pac

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 }

hdu 3440 House Man