Description
Kirill the gardener has got a new task. He has to water the flowers growing on the huge flowerbed! It should be mentioned that the bed is very long and narrow at the same time. So from bird’s-eye view (and Kirill growth too) it looks like a straight line, where n points-flowers are located at regular intervals. For this job Kirill has a watering pot of infinite volume and smartwatch that shows moisture content of each flower before watering. The watering takes too much time, so the most dried flowers can die, which is unacceptable. So Kirill decided to water the flowers in order of their non-decreasing dryness. On the other hand, he wants to finish the watering as soon as possible, because there are a lot of other interesting things.
Assume that watering of one flower and walking between two neighbor flowers takes Kirill one minute. Can you figure out the time in which the young gardener will complete his job if he acts optimally? Initially Kirill stands near the leftmost flower.
Input
The first line contains an integer n ( 1≤n≤105 ) — it’s amount of flowers in the flowerbed. The second line contains n integers separated by spaces — it‘s moisture content of flowers given in order of their positions in the flowerbed from left to right. Moisture content is an integer from 1 up to 109 (including both).
Output
In the only line print an integer — the minimal time in which Kirill would complete watering.
题意
给定一个 n ,以及编号为 1-n 的 n 个数字。已知起点为 1 ,假设移动一个位置花费的时间为 1 ,对某位置的数作处理花费的时间为 1 ,要求必须若仍存在未处理且比当前位置上的数更小的数字,则不能处理当前位置的数,在选择最优策略的情况下,问处理完 n 个数的最小时间。
分析
显然,每个数都必须处理一遍,则时间 n 的花费是必须的。
根据题意可以知道每次处理的数一定是当前未处理数中最小的数(可能有多个数同时最小)。在单次处理值为 x 的数时,为了使花费时间最小,必然是从同样值为 x 的最左坐标向最右坐标移动,或从最右坐标向最左坐标移动。
考虑从上一个大小的值(最左坐标和最右坐标分别为 li,ri )到处理下一个值(最左坐标和最右坐标分别为 li+1,ri+1 ),在保证上一个处理中移动最优的情况下,为处理下一个值的移动必然符合
其中 dp[i][0] 表示在结束第 i 大的值的操作后处于该值最左端点的最小时间, dp[i][1] 表示在结束第 i 大的值的操作或处于该值最右端点的最小时间。
代码
#include<bits/stdc++.h>
using namespace std;
const int N = 100000 + 10;
struct Node {
int dry, idx;
}p[N];
bool operator<(Node a,Node b) {
if(a.dry == b.dry)
return a.idx < b.idx;
return a.dry < b.dry;
}
long long myabs(long long a) {
return a > 0 ? a : -a;
}
long long dp[N][2];
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&p[i].dry), p[i].idx = i;
sort(p+1, p+n+1);
int pos = 1;
long long cnt = n;
vector< pair<long long, long long> > vec;
for(int i=1, l, r;i<=n;i++) {
l = p[i].idx;
r = p[i].idx;
for(i++;i<=n;i++) {
if(p[i].dry == p[i-1].dry)
r = p[i].idx;
else{
i--;
break;
}
}
vec.push_back(make_pair(l,r));
cnt += r-l;
}
dp[0][1] = myabs(vec[0].first - 1ll);
dp[0][0] = myabs(vec[0].second - 1ll);
for(int i=1;i<vec.size();i++)
{
dp[i][1] = min( myabs(vec[i-1].first - vec[i].first) + dp[i-1][0], myabs(vec[i-1].second - vec[i].first) + dp[i-1][1]);
dp[i][0] = min( myabs(vec[i-1].first - vec[i].second) + dp[i-1][0], myabs(vec[i-1].second - vec[i].second) + dp[i-1][1]);
}
printf("%I64d\n", min(dp[vec.size()-1][0], dp[vec.size()-1][1]) + cnt);
}