ural 2072 - Kirill the Gardener 3 - dp

題意:有n朵花,要求按照權值遞增的順序澆水,澆水一次話一個時間,走一個單位長度花費一個單位時間。

一共n朵花,那麼可以先計算出走路用的時間,然後加上n就是總時間,對於權值相同的所有花,就可以只考慮兩個端點,這樣中間的一定會路過,先走左端點還是先走右端點是不確定的,可以先按照權值大小進行排序,然後按照權值遞增處理成多個不同的區間,之後用動態規劃處理,dp[i][0]表示走到第i個區間左端點再走右端點的最小時間,dp[i][1]表示先走到第i個區間的右端點再走左端點的最小時間,走路用的最小時間就是最後一個區間先走左和先走右的最小值,加上澆水用的時間就得到最終結果。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
using namespace std;
const int INF = 0x3f3f3f3f;
typedef long long ll;
struct node {
    int dx, x;
}id[100005], dp[100005];
bool cmp(node a, node b) {
    if(a.x != b.x)
        return a.x < b.x;
    return a.dx < b.dx;
}
ll d[100005][2] = {0};
int main() {
    int n, i, j;
    while(~scanf("%d", &n)) {
        for(i = 0; i < n; i++) {
            id[i].dx = i;
            scanf("%d", &id[i].x);
        }
        sort(id, id + n, cmp);
        memset(dp, 0, sizeof(dp));
        dp[1].dx = dp[1].x = id[0].dx;
        int m = 1;
        for(i = 1; i < n; i++) {
            if(id[i].x == id[i - 1].x) {
                dp[m].x = id[i].dx;
            }
            else {
                m++;
                dp[m].x = dp[m].dx = id[i].dx;
            }
        }
        int ans = 0;
        memset(d, 0, sizeof(d));
        int cur = 0;
        for(i = 1; i <= m; i++) {
            d[i][0] = min(d[i - 1][0] + abs(dp[i - 1].dx - dp[i].x) + dp[i].x - dp[i].dx, d[i - 1][1] + abs(dp[i - 1].x - dp[i].x) + dp[i].x - dp[i].dx);
            d[i][1] = min(d[i - 1][0] + abs(dp[i - 1].dx - dp[i].dx) + dp[i].x - dp[i].dx, d[i - 1][1] + abs(dp[i - 1].x - dp[i].dx) + dp[i].x - dp[i].dx);
        }
        printf("%I64d\n", min(d[m][0], d[m][1]) + n);
//        break;
    }
    return 0;
}

發佈了67 篇原創文章 · 獲贊 1 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章