漂流
题目描述
暑期将至,小鼠 Jack 决定到鼠国最著名的蓝阴河去玩漂流。
我们假定蓝阴河宽度为 m 米,其中每隔一定距离就会有一处障碍(为了
让漂流更刺激~),一共有 n 个障碍,第 i 个障碍的 Xi-Yi 米处是一个开口,只有从障碍中间的开口处才能通过(开口包含 Xi,Yi)。现在 Jack 位于 1 号障碍的开口处,他要划艇依次通过这些障碍,但是 Jack 比较懒,每当他向左或向右移动 1 米,他就会消耗 1 点体力。由于水流的作用,Jack 向前移动不消耗体力。现在,他希望知道,他依次通过这些障碍所需要消耗的最小体力是多少。
思路
贪心?
DP?空间复杂度O(nm),时间复杂度O(nm²)
所以我们能不能采用一些技巧优化DP呢?显然可以。
好吧我们重新引入贪心的思路,提出下面的结论:
最优的方案,一定是从某些障碍的开口边缘处直接游向另一
些障碍的开口边缘处(不一定是相邻的两个障碍,但是一定
能直接游过去)
那么此时的DP方程就很好看了:设f[i][k]表示走到第i个障碍的开
口边缘处需要消耗的最少体力(k=0代表左边缘,1代表右边缘)
f[i][k]=min(f[j][l]+|x[j][l]-x[i][k]|) (j
* 但是*
这明显就是水题啊!!!!
代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=1e5+5;
const int M=1e9+5;
int n,m,zuo[N],you[N],ans=0,pos,now;
int main()
{
scanf("%d%d",&n,&m);
// memset(zuo,0,sizeof(zuo));
// memset(you,0,sizeof(you));
scanf("%d%d",&zuo[1],&you[1]);
pos=zuo[1];
for (int i=2;i<=n;i++)
{
scanf("%d%d",&zuo[i],&you[i]);
if (zuo[i]<=pos&&you[i]>=pos) continue;
if (abs(pos-zuo[i])>abs(pos-you[i]))
{
ans+=abs(pos-you[i]);
pos=you[i];
}
else
{
ans+=abs(pos-zuo[i]);
pos=zuo[i];
}
}
printf("%d",ans);
return 0;
}