hdu3440 差分约束系统

本文介绍使用差分约束系统解决特定算法问题的方法。通过分析房屋布局问题,讲解如何建立不等式,并采用最短路径算法求解最大值。文章包含详细的解题思路和AC代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

解题报告

题目 http://acm.hdu.edu.cn/showproblem.php?pid=3440

算法 :差分约束系统

思路 :读懂题后想了很久,最后想到的是二分加判定,但是如何判定却不会,后来才知道这是道差分约束系统的题,(听说官方解题报告是极其诡异的贪心,没有看到)。有了差分约束这个念头,就不难再去思考此题了。差分约束系统解决的是一组不等式的解,对于此题,不等式还是比较好写的,

1. 位置相邻的两个house间距>= 1<id, id - 1, -1>(2=< id <= N)

2. 高度相邻的两个house间距 <= D<min(f[i-1].id, f[i].id), max(f[i-1].id, f[i].id), D>(2 <= i <= N)

因为是求在大值,因此用最短路,要注意的是最短路的起始点和终止点要跟与最低点和最高点的相对位置而定,要保证从左往右(因为建图的坐标位置就是从左往右的)。也就是令dis[min(minh,maxh)] = 0, 输出dis[max(minh, maxh)]即可,由于图肯定是联通的,应此不用多加源点。

由于maxn×D = 1 × 10^9, 因此初始值INF一定要很大,悲剧的检查了一上午,最后发现是这个问题,悔死我了!INF = 0x3fffffff就差不多了.214000000都不行。。。。。。

 

提交情况 wrong answer N INF值偏小(210000000))

收获与经验 :检查程序问题是一定要全面,不能只看主要的函数功能部分。看清楚数据范围。对差分约束系统函数不是很熟,需要再做题。

AC code

//代码中最短路径分别用了SPFAbellman

#include <stdio.h>

#include <algorithm>

 

using namespace std;

#define MAXN 1010

#define INF 0x3fffffff

#define MIN(a, b) ((a) < (b) ? (a) : (b))

#define MAX(a, b) ((a) > (b) ? (a) : (b))

 

struct NODE{

    int st, to, len, next;

};

NODE edges[MAXN * 100];

inthead[MAXN], ad;

 

struct NOde{

    int high, xu;

} tall[MAXN];

intdis[MAXN], queue[MAXN], in[MAXN], times[MAXN];

int n, D;

 

bool comp(const NOde A, const NOde B){

    return A.high < B.high;

}

voidclear(){

    memset(head, -1, sizeof(head));

    ad = 0;

}

void insert(int u, int v, int d){

    edges[ad].st = u; edges[ad].to = v; edges[ad].len = d; edges[ad].next = head[u]; head[u] = ad ++;

}

void built(int s, int t){

    clear();

    for(int i = 1; i < n; i ++){

       insert(i, i - 1, -1);

       insert(MIN(tall[i].xu, tall[i - 1].xu), MAX(tall[i].xu, tall[i - 1].xu), D);

    }

}

int SPFA(int rS, int rT){

    int front = 0, tail = 0, i, u, v, p;

    memset(in, 0 , sizeof(in));

    memset(times, 0, sizeof(times));

    for(i = 0; i < n; i ++) dis[i] = INF;

    queue[tail++] = rS;

    dis[rS] = 0;

    in[rS] = 1;

    times[rS] ++;

    while(front != tail){

       u = queue[front];

       front = (front + 1) % MAXN;

       in[u] = 0;

       for(p = head[u]; ~p; p = edges[p].next){

           v = edges[p].to;

           if(dis[v] > dis[u] + edges[p].len){

              dis[v] = dis[u] + edges[p].len;

              if(!in[v]){

                  queue[tail] = v;

                  tail = (tail + 1) % MAXN;

                  in[v] = 1;

                  times[v] ++;

                  if(times[v] > n) return -1;

              }

           }

       }

    }

    return dis[rT];

}

intbellman(int er, int et){

    int i, j;

    for(i = 0; i < n; i ++) dis[i] = INF;

    dis[er] = 0;

    for(i = 0; i < n; i ++){

       for(j = 0; j < ad; j ++)

           if(dis[edges[j].st] < INF && dis[edges[j].to] > dis[edges[j].st] + edges[j].len)

              dis[edges[j].to] = dis[edges[j].st] + edges[j].len;

    }

    for(j = 0; j < ad; j ++)

       if(dis[edges[j].to] > dis[edges[j].st] + edges[j].len) return -1;

    return dis[et];

}

int main(){

    int CASE, T, i, s, t;

    scanf("%d", &CASE);

    for(T = 1; T <= CASE; T ++){

       scanf("%d %d", &n, &D);

       s = t = 0;

       for(i = 0; i < n; i ++){

           scanf("%d", &tall[i].high);

           tall[i].xu = i;

       }

       sort(tall, tall + n, comp);

       s = tall[0].xu;

       t = tall[n - 1].xu;

       built(s, t);

       int ans = SPFA(MIN(s, t), MAX(s, t));

       //int ans = bellman(MIN(s, t), MAX(s, t));

       printf("Case %d: %d\n", T, ans);

    }

    return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值