• 【CF-1012 C. Hills】DP


    Hills

    题意

    有n个土堆,第(i)个土堆高为(a[i]),现在要在土堆上面建造房子,只有当(a_i>a_{i-1} and a_i >a _{i+1})

    才可以把房子建到第(i)个土堆上,有一台推土机每小时可以推掉一个土堆一米,对于所有可能的(k),

    输出建造至少(k)座房子需要最少的时间。

    题解

    参考博客

    (dp[i][j][0/1])表示在前(i)个土堆中,建造(j)坐房子,第(i)个土堆是否建造需要的最小时间。

    如果第(i)个土堆,要建造房子:

    只能从(dp[i-1][j-1][0])转移来。那么要保证(a_{i-1}<a_i)

    如果此时第(i-2)个土堆,也建造了房子,就要保证(a_{i-1}<a_{i-2} ,a_{i-1}<a_i),

    此时(dp[i][j][1])并没有考虑(a_{i+1})的高度,但是(dp[i][j][0])考虑了(a_{i-1})的高度,如下。

    (i)个土堆不建造房子:考虑第(i-1)是否建造房子,如果建造了要保证(a_i<a_{i-1})

    没有就直接转移。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int N=5e3+10;
    const int inf=0x3f3f3f3f;
    typedef long long ll;
    
    int arr[N],dp[N][N][3];
    int main()
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&arr[i]);
        memset(dp,inf,sizeof(dp));
        dp[1][1][1]=dp[1][0][0]=dp[0][0][0]=0;
        for(int i=2;i<=n;i++)
        {
            for(int j=0;j<=(i+1)/2;j++)
            {
                dp[i][j][0]=min(dp[i-1][j][1]+max(0,arr[i]-arr[i-1]+1),
                                dp[i-1][j][0]);
                dp[i][j][1]=min(dp[i-2][j-1][0]+max(arr[i-1]-arr[i]+1,0),
                                dp[i-2][j-1][1]+max(0,arr[i-1]-min(arr[i-2],arr[i])+1));
            }
        }
        for(int i=1;i<=(n+1)/2;i++)
            printf("%d ",min(dp[n][i][0],dp[n][i][1]));
        printf("
    ");
        return 0;
    }
    
  • 相关阅读:
    BFPRT算法O(n)解决第k小的数
    Manacher练习
    KMP全家桶练习
    Codeforces Round #552 (Div. 3)
    Manacher's Algorithm
    poj 2559 (单调栈)
    单调队列
    单调栈
    multiset用法
    poj3660 Cow Contest(Floyd-Warshall方法求有向图的传递闭包)
  • 原文地址:https://www.cnblogs.com/valk3/p/12971195.html
Copyright © 2020-2023  润新知