URAL 2072. Kirill the Gardener 3(dp)

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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值