HDU--3440(差分约束)

2015-01-10 15:06:21

思路:很好的一道差分约束题,拥有灵活的建图。

  由于题目求的是从起点(最矮的房子)到终点(最高的房子)的有向距离最大值,那么在建图以及跑最短路时要特别注意方向。

  首先按照房子的读入顺序给房子编号为1~N,用结构体记录下房子的高度、编号,然后按照高度升序排序。

  这样排完序后自然就是从第1个房子一直跳到第N个房子。

  约束条件:排序前:pos[i] - pos[i - 1] >= 1

        排序后:比较一下id[i] , id[i - 1]的大小(用id[i]来记录排序后第i个房子在输入中的位置)

        (1)如果id[i] > id[i - 1]说明从排序后第i-1个房子跳到第i个房子要往后跳 pos[id[i]] - pos[id[i - 1]] >= D

        (2)如果id[i] < id[i - 1]说明从排序后第i-1个房子跳到第i个房子要往前跳 pos[id[i - 1]] - pos[id[i]] >= D

  最后,要判断下id[1]和id[N]的大小,选取小的为起点,大的为终点来跑最短路,这样答案才为正。(我就被坑在这好久。。。)

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <cmath>
  5 #include <vector>
  6 #include <map>
  7 #include <set>
  8 #include <stack>
  9 #include <queue>
 10 #include <iostream>
 11 #include <algorithm>
 12 using namespace std;
 13 #define lp (p << 1)
 14 #define rp (p << 1|1)
 15 #define getmid(l,r) (l + (r - l) / 2)
 16 #define MP(a,b) make_pair(a,b)
 17 typedef long long ll;
 18 typedef unsigned long long ull;
 19 typedef pair<int,int> pii;
 20 const int INF = (1 << 30) - 1;
 21 const int maxn = 1010;
 22 
 23 int T,N,D;
 24 int first[maxn],ecnt;
 25 int inq[maxn],cnt[maxn],dis[maxn];
 26 
 27 struct edge{
 28     int u,v,next,cost;
 29 }e[maxn << 1];
 30 
 31 struct node{
 32     int h,id;
 33 }t[maxn];
 34 
 35 bool cmp(node a,node b){
 36     return a.h < b.h;
 37 }
 38 
 39 void Add_edge(int u,int v,int c){
 40     e[++ecnt].next = first[u];
 41     e[ecnt].u = u;
 42     e[ecnt].v = v;
 43     e[ecnt].cost = c;
 44     first[u] = ecnt;
 45 }
 46 
 47 bool Spfa(int s){
 48     queue<int> Q;
 49     memset(inq,0,sizeof(inq));
 50     memset(cnt,0,sizeof(cnt));
 51     fill(dis + 1,dis + N + 1,INF);
 52     dis[s] = 0;
 53     cnt[s] = 1;
 54     Q.push(s);
 55     while(!Q.empty()){
 56         int x = Q.front(); Q.pop();
 57         inq[x] = 0;
 58         for(int i = first[x]; ~i; i = e[i].next){
 59             int v = e[i].v;
 60             if(dis[v] > dis[x] + e[i].cost){
 61                 dis[v] = dis[x] + e[i].cost;
 62                 if(inq[v] == 0){
 63                     inq[v] = 1;
 64                     if(++cnt[v] > N) return false;
 65                     Q.push(v);
 66                 }
 67             }
 68         }
 69     }
 70     return true;
 71 }
 72 
 73 int main(){
 74     scanf("%d",&T);
 75     for(int tt = 1; tt <= T; ++tt){
 76         memset(first,-1,sizeof(first));
 77         ecnt = 0;
 78         scanf("%d%d",&N,&D);
 79         for(int i = 1; i <= N; ++i){
 80             scanf("%d",&t[i].h);
 81             t[i].id = i;
 82             //pos[i] - pos[i - 1] >= 1 --> pos[i - 1] <= pos[i] - 1
 83             Add_edge(i,i - 1,-1);
 84         }
 85         sort(t + 1,t + N + 1,cmp);
 86         for(int i = 2; i <= N; ++i){
 87             if(t[i].id > t[i - 1].id){ 
 88                 //pos[t[i].id] - pos[t[i - 1].id] <= D
 89                 //pos[t[i].id] <= pos[t[i - 1].id] + D
 90                 Add_edge(t[i - 1].id,t[i].id,D);
 91             }
 92             else{                      
 93                 //pos[t[i - 1].id] - pos[t[i].id] <= D
 94                 //pos[t[i - 1].id] <= pos[t[i].id] + D
 95                 Add_edge(t[i].id,t[i - 1].id,D);
 96             }        
 97         }
 98         printf("Case %d: ",tt);
 99         int st = min(t[1].id,t[N].id);
100         int ed = t[1].id + t[N].id - st;
101         if(Spfa(st)) printf("%d\n",dis[ed]);
102         else printf("-1\n");
103     }
104     return 0;
105 }

 

posted @ 2015-01-10 15:14  Naturain  阅读(142)  评论(0编辑  收藏  举报