ural 2072 - Kirill the Gardener 3 - dp

来源:互联网 发布:手机cad软件 编辑:程序博客网 时间:2024/04/28 13:29

题意:有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;}

0 0