链接:
http://acm.hdu.edu.cn/showproblem.php?pid=2363
题目大意:
小明从家里走到学校去考试, 路上有各个交叉点,它们有自己的海拔高度。 小明从家里走到学校的路上,必然会经过不同的交叉点,因此会不断的走上走下,忐忐忑忑,这让他很不安,会影响他考试的发挥。因此,他要选择一条起伏最小的路去学校。所谓的“起伏最小”,是指这条路上海拔最高的点与海拔最低的点的差值最小。
在起伏最小的前提下,还要求出路程距离最短。
分析与总结:
这题让我想起以前做过的一题,HDU1598,不过那时是用最小生成树做的,而且那题只需要输出最小差而不用求最短路。
这题中,根据高度差的递增,明显满足条件的路径数量也是递增的,因此可以二分“高度差”。
光有“高度差”还是不够的,因为“起伏值”等于最大高度减最小高度, 所以需要再枚举最小高度(下限low), 在根据最小高度+“高度差”得到最大高度(上限up), 有了low和up这两个条件,就可以进行求限制最短路。
做这题WA了有20+, 因为在求最短路时没有排除掉超过“上限”的边。
之后试着最小生成树的方法做了下,先求出“最小差”和上限与下限,然后再求最短路,但是WA了,纠结中...
代码:
二分+枚举+最短路
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int INF = 0x7fffffff;
const int VN = 120;
const int EN = 10005;
int n;
int m;
int size;
int head[VN];
int h[VN];
int order[VN];
int d[VN];
int up; // 上界
int low; // 下界
bool inq[VN];
struct Edge{
int v,next;
int w;
}E[EN];
void addEdge(int u,int v,int w){
E[size].v=v;
E[size].w=w;
E[size].next=head[u];
head[u]=size++;
}
int SPFA(int src){
memset(inq, 0, sizeof(inq));
for(int i=0; i<=n; ++i)d[i]=INF;
d[src]=0;
if(h[src]<low || h[src]>up) return INF; // 起点不符合条件直接返回INF
queue<int>q;
q.push(src);
while(!q.empty()){
int u=q.front(); q.pop();
if(h[u]<low || h[u]>up) continue; // 排除符合和限制的
inq[u] = false;
for(int e=head[u]; e!=-1; e=E[e].next)if(h[E[e].v]>=low&&h[E[e].v]<=up){//有限制
int tmp=d[u]+E[e].w;
if(d[E[e].v] > tmp){
d[E[e].v] = tmp;
if(!inq[E[e].v]){
inq[E[e].v]=true;
q.push(E[e].v);
}
}
}
}
return d[n];
}
int main(){
int T, u, v;
int len, Min, Max;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
size=0;
memset(head, -1, sizeof(head));
for(int i=1; i<=n; ++i){
scanf("%d", &h[i]);
order[i]=h[i];
if(h[i]<Min)Min=h[i];
if(h[i]>Max)Max=h[i];
}
for(int i=0; i<m; ++i){
scanf("%d%d%d",&u,&v,&len);
addEdge(u,v,len);
addEdge(v,u,len);
}
sort(order+1, order+1+n);
int left=0, right=Max-Min+1, mid;
int ans, dif=INF, minlen=INF;
while(left < right){ // 二分“高度差”
mid = (left+right)>>1;
bool flag=false;
for(int i=1; i<=n; ++i){ // 枚举最低海拔
low=order[i];
up=order[i]+mid; // 得到海拔上限
int tmp=SPFA(1);
if(tmp!=INF){
flag=true;
ans=tmp;
break;
}
}
if(flag){
right=mid;
if(mid<dif){
dif=mid;
minlen=ans;
}
else if(mid==dif && ans<minlen){
minlen=ans;
}
}
else{
left=mid+1;
}
}
printf("%d %d\n", dif, minlen);
}
return 0;
}
—— 生命的意义,在于赋予它意义。
分享到:
相关推荐
acm入门之枚举搜索,学校第一次acm培训,包括枚举及其优化,dfs和bfs
1. **基础算法**:如排序(快速排序、归并排序、冒泡排序等)、搜索(二分查找、深度优先搜索、广度优先搜索等)。 2. **动态规划**:这类问题通常需要找到一种状态转移方程,通过递推或自底向上的方法求解。例如...
4. **排序与搜索**:快速排序、归并排序、二分查找等经典算法在HDU题目中经常出现。解题报告会深入讲解这些算法的原理和应用场景,并给出高效的实现代码。 5. **字符串处理**:包括KMP算法、Manacher's Algorithm等...
hdu 3341(ac自动机+状态压缩) 题意:容易理解... 思路:首先一开始容易想到要用到dp,开设一个dp[41][41][41][41][501]的数组来解决,但是明显内存已经超出范围了,于是就想如何减少内存呢?只要知道A、T、C、G其中...
ACM HDU 题目分类是指对 HDU 在线判题系统中题目的分类,总结了大约十来个分类。这些分类将有助于编程选手更好地理解和解决问题。 DP 问题 DP(Dynamic Programming,动态规划)是一种非常重要的算法思想,在 ACM ...
离线OJ题库是为编程爱好者和程序员提供的一种便捷的学习资源,主要包含来自不同在线判题系统(如HDU - 浙江大学多模式在线评测系统,ZJU - 浙江大学在线评测系统等)的编程题目。这类题库通常包含多种编程语言的题目...
1. **基础算法**:如排序(冒泡、选择、插入、快速、归并等)、搜索(线性、二分、深度优先、广度优先等)。 2. **高级算法**:包括动态规划(状态转移、记忆化搜索)、贪心策略、回溯法、分支限界法等。 3. **...
此外,最短路问题的变种,如带有容量限制的最短路、多目标最短路等,也值得进一步研究。 总结,最短路问题在理论和实践上都有着重要的地位。理解并掌握各种算法不仅可以深化对图论的理解,还能在实际项目中发挥关键...
本人准备2020年保研机试时刷的题目(虽然最后机试取消了,...来自某中流985,在HDU和vjudge平台上大概刷了400道。本文件地图(excel表格)包含了绝大部分我刷过的题目,笔记中具有思路、代码、总结和心得。 大佬勿入!
hdu 5007 Post Robot 字符串枚举。 暴力一下就可以了。
ACM hdu 线段树题目+源代码 线段树是一种非常重要的数据结构,它广泛应用于算法竞赛和实际编程中。今天,我们将通过 ACM hdu 的几个题目来学习和掌握线段树的基本概念和应用。 线段树的基本概念 线段树是一种...
【标题】"hdu.rar_HDU 1089.cpp_OJ题求和_hdu_horsekw5_杭电obj" 提供的信息是关于一个压缩文件,其中包含了一个名为 "HDU 1089.cpp" 的源代码文件,这个文件是为了解决杭州电子科技大学(Hangzhou Dianzi ...
HDU二分匹配及其应用,此PPT是刘春英老师版权所有, 特此贡献给广大编程爱好者,特别是对于ACMer
"hdu 1695 GCD(欧拉函数+容斥原理)" 题目大意是:给定 a, b, c, d, k,找到一队 x, y,满足 g(x, y) = k,且 x ∈ [1, b], y ∈ [1, d],问有多少对符合要求的 (x, y)。 思路是:gcd(x, y) == k 解释 x, y 都能...
杭电ACM课件2014版之(HDUACM2010版_13)二分匹配及其应用
HDU 300+ AC 代码集合是一个包含超过300个已通过验证的算法解决方案的资源,这些代码主要用于解决各类计算机编程竞赛中的问题。这些竞赛通常由杭州电子科技大学(HDU)主办,旨在提升参赛者的算法设计、编程和问题...
一个十分简单的程序,能够ac杭电hdu的第2050题,无注释,简单明了
在IT领域的编程竞赛中,HDU(HaoDong University)OJ(Online Judge)是一个备受推崇的在线编程平台,提供了大量的算法问题供参赛者挑战和学习。根据给定文件的信息,我们可以深入探讨HDU ACM题目分类中的几个关键...
Problem Description 话说,经过了漫长的一个多月,小明已经成长了许多,所以他改了一个名字叫“大明”。 这时他已经不是那个只会做100以内加法的那个“小明”了,...请在一行里面输出输出A+B的值,请输出最简形式。
在C++编程语言中,`new`和`delete`是两个关键的操作符,它们与C语言中的`malloc`和`free`有所不同。`new`不仅分配内存,还会根据指定的类型调用对应的构造函数来初始化对象,而`malloc`仅仅分配内存,不涉及对象的...