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 ≤ 10 5) — 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 10 9 (including both).
Output
In the only line print an integer — the minimal time in which Kirill would complete watering.
Example
input
6
3 2 5 6 2 5
output
21
input
6
4 1 3 2 2 3
output
16
题目描述
有n朵花,每个花有一个权值,权值越小越优先浇水,浇水和移动一个位置都需要一个单位时间,初始位置在第一个位置,问把所有的花浇一遍需要的最小的时间是多少.
解题思路
先将花按照权值进行排序,规定相同权值的花为一个区间,贪心策略如果要使结果最小,一定是从区间的最左边或者最右边和其他的区间的最左边或者最右边进行相连.
于是则有dp思想:
dp[i][0]表示第 i 个区间的浇水方向是从最右侧到最左侧;
dp[i][1]表示第 i 个区间的浇水方向是从最左侧到最右侧.
prel,prer 标记上一个区间的左端点和右端点.
则dp[i][0]=min(从第 i-1区间的左端点(dp[i-1][0]) -> 第 i 区间的右端点,从第 i-1 区间的右端点(dp[i-1][1]) ->第 i 区间的右端点)
=min(dp[i-1][0]+abs(prel-a[j].id),dp[i-1][1]+abs(prer-a[j].id)),
同理,dp[i][1]=min(dp[i-1][1]+abs(prer-a[i].id),dp[i-1][0]+abs(prel-a[i].id)),
如图为样例2 dp[i][0].
代码实现
#include<bits/stdc++.h>
#define IO ios::sync_with_stdio(false);\
cin.tie(0);\
cout.tie(0);
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f
const int maxn = 1e5+10;
ll dp[maxn][2];
//dp[i][0] 代表第 i 个区间先到右端点,再由右端点走至左端点
//dp[i][1] 代表第 i 个区间先到左端点,再由左端点走至右端点
struct node
{
ll val;
ll id;
}a[maxn];
bool cmp(node x,node y)
{
if(x.val==y.val)
return x.id<y.id;
else return x.val<y.val;
}
int main()
{
IO;
ll n;
cin>>n;
memset(dp,INF,sizeof(dp));
dp[0][1]=0,dp[0][0]=0;
for(int i=1;i<=n;i++)
{
cin>>a[i].val;
a[i].id=i;
}
sort(a+1,a+n+1,cmp);
ll sec=1;
ll prel=0,prer=0;
ll res=0;
for(int i=1;i<=n;i++)
{
int j=i+1;
while(a[i].val==a[j].val&&j<=n) j++;
--j;
res+=abs(a[j].id-a[i].id);
dp[sec][0]=min(dp[sec-1][0]+abs(prel-a[j].id),dp[sec-1][1]+abs(prer-a[j].id));
dp[sec][1]=min(dp[sec-1][1]+abs(a[i].id-prer),dp[sec-1][0]+abs(a[i].id-prel));
++sec;
prel=a[i].id,prer=a[j].id;
i=j;
}
cout<<min(dp[sec-1][1],dp[sec-1][0])+res+n-1<<endl;
return 0;
}