题意:
有N个在一条直线上的房子,每个房子有着不同的高度,
一个超人可以将这些房子左右移动但不能改变房子之间的相对位置
现在超人要从最矮的房子跳到刚好比他高的房子上面,且每次跳的房子都要比当前房子要高
最后超人肯定会跳到最高的房子上面,现在给出超人能够跳的最远距离,
问: 如何摆放这些房子,使得超人能够经过所有的房子跳到最高的房子,又要使最矮的房子和最高的房子之间的距离最远?
注意一共要跳N-1次
分析:
为什么我会放上题目翻译呢?因为这道题真的不好理解
因为这个crazy man一共要跳N-1次,因此每一座楼都会到达,每次一定会跳到高度紧接着的那座楼
而且每个房子不能在相同的位置
这样我们就能得到一些关系了:
对于高度相邻的两座楼
i
i
和:
s(max(i,j))−s(min(i,j))<=T,s(max(i,j))<=s(min(i,j))+T
s
(
m
a
x
(
i
,
j
)
)
−
s
(
m
i
n
(
i
,
j
)
)
<=
T
,
s
(
m
a
x
(
i
,
j
)
)
<=
s
(
m
i
n
(
i
,
j
)
)
+
T
且
s(i+1)−s(i)>=1,s(i)<=s(i+1)−1
s
(
i
+
1
)
−
s
(
i
)
>=
1
,
s
(
i
)
<=
s
(
i
+
1
)
−
1
直接建图即可
Q.
这道题求的是最大值,为什么我们要跑一个最短路呢
A.
实际上,我们是通过转化,才把原先的问题变成了一道图论
我们由问题的条件得到的不等式就是最短路的形式,与题设无关
所以还是要用最短路求解
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
const int INF=1e9;
const int N=1010;
int n,m,dis[N],cnt[N],st[N],tot=0;
bool in[N];
struct po{
int h,id;
};
po a[N];
struct node{
int y,nxt,v;
};
node way[N*10];
int cmp(const po &A,const po &B) {return A.h<B.h;}
void add(int u,int w,int z)
{
tot++;
way[tot].y=w;way[tot].v=z;way[tot].nxt=st[u];st[u]=tot;
}
int Bellman(int s,int t)
{
queue<int> Q;
memset(dis,0x7f,sizeof(dis));
memset(cnt,0,sizeof(cnt));
memset(in,0,sizeof(in));
Q.push(s); in[s]=1; dis[s]=0;
while (!Q.empty())
{
int now=Q.front(); Q.pop();
in[now]=0;
for (int i=st[now];i;i=way[i].nxt)
if (dis[way[i].y]>dis[now]+way[i].v)
{
dis[way[i].y]=dis[now]+way[i].v;
if (!in[way[i].y])
{
in[way[i].y]=1;
if (++cnt[way[i].y]>n) return -1;
Q.push(way[i].y);
}
}
}
return dis[t];
}
int main()
{
int T;
scanf("%d",&T);
for (int cas=1;cas<=T;cas++)
{
memset(st,0,sizeof(st)); tot=0;
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) scanf("%d",&a[i].h),a[i].id=i;
sort(a+1,a+1+n,cmp);
for (int i=1;i<n;i++)
{
int x=a[i].id;
int y=a[i+1].id;
if (x>y) swap(x,y);
add(x,y,m);
add(i+1,i,-1);
}
printf("Case %d: %d\n",cas,Bellman(min(a[1].id,a[n].id),max(a[1].id,a[n].id)));
}
return 0;
}