zoukankan      html  css  js  c++  java
  • 洛谷 P2858 奶牛零食

    https://www.luogu.org/problemnew/show/P2858

    毫无疑问区间dp。

    [区间dp入门]

    我们定义dp[i][j]表示从i到j的最大收益,显然我们需要利用比较小的区间来推出更大的区间。

    初始化dp[i][i]=单价,这里先不考虑第几天卖。

    现在我们来确定小区间与大区间的关系,继而写出递推方程式。

    每一个区间长度为一的块,想要扩大区间长度,那么只需要考虑对于现区间的左右端点的相邻点,我们可以通过比较确定是取左邻点还是右邻点(i,j分别表示左右端点)。

    $$dp[i][j]=max(dp[i-1][j],dp[i][j-1])[i,j]$$

    现在我们不管取左边的点还是右边的点,没有动过的点卖的天数县比与上一个状态晚卖了一天,所以每一个物品要加一次单价。

    那么需要(a[k]表示单价)

    $$dp[i][j]+=sum_{k=i}^{k<=j}a[k]$$

    为了简便$sum_{k=i}^{k<=j} a[k]$提前用前缀和统计一下就好了。

    所以外层循环枚举区间长度,内层循环枚举左端点。

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <queue>
    #include <map>
    using namespace std;
    #define LL long long
    #define mod int(1e9+7)
    #define wlz 1234567890
    int n,ans1,ans2;
    int a[2110],sum[2110],dp[2110][2110];
    int main()
    {
    //    cout<<sizeof(dp)/1024/1024;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            sum[i]=sum[i-1]+a[i];
        }
        for(int i=n;i>=1;i--) 
        {
            for(int j=i;j<=n;j++) 
            {
                dp[i][j]=max(dp[i+1][j],dp[i][j-1]);
                dp[i][j]+=(sum[j]-sum[i-1]);
            }
        }
        printf("%d",dp[1][n]);
    }
  • 相关阅读:
    团队绩效打分
    软件对标分析
    目前校园百晓生APP与CSDN软件的对比
    Alpha版
    团队项目第一阶段成果展示
    意见汇总
    团队第一阶段冲刺评价
    冲刺(十)
    【WPF学习】第五十八章 理解逻辑树和可视化树
    【WPF学习】第五十七章 使用代码创建故事板
  • 原文地址:https://www.cnblogs.com/rmy020718/p/9523742.html
Copyright © 2011-2022 走看看