zoukankan      html  css  js  c++  java
  • P2893 [USACO08FEB]修路

    直入主题。 农夫约翰想改造一条路,原来的路的每一段海拔是Ai,修理后是Bi花费|A_i–B_i|。我们要求修好的路是单调不升或者单调不降的。求最小花费。

    数据范围:n<=2000,0≤ Ai ≤ 1,000,000,000

    (说真的,时隔几个月,发现这题其实挺简单的)

    最一开始,就打了一个贪心。

    #include<bits/stdc++.h>//本人打题目时很喜欢万能头
    using namespace std;
    const int maxn=2010;
    long long  n,ans1,ans2;
    long long a[maxn];
    
    
    int main()
    {
        scanf("%lld",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&a[i]);
        }
        for(int i=1;i<n;i++)
        {
            if(a[i]>a[i+1])
            ans1+=abs(a[i]-a[i+1]);
            //printf("%d
    ",ans1);
        }
        for(int i=n;i>1;i--)
        {
            if(a[i]>a[i-1])
            ans2+=abs(a[i-1]-a[i]);
            //printf("%d
    ",ans2);
        }
        printf("%d",min(ans1,ans2));
        return 0;
    }

    此贪心思路 很容易发现,如果想要最小值的话,凹下去的土块一定会被填起来,而且填的高度一定会使这个土块和两侧最低的那个相平(比如样例第三个土块,填起来一定会和 二 一样高)于是考虑跑两遍,一个单增,一个单减。

    结果:40分

    。。。

    随手一组hack数据:

    9 5 5 5 1 1 1 5 5 5;

    我没有及时更新高度,以至于会有后效性。 于是我每次减完会把它更新一次高度。 但是发现,还是会有后效性,hack数据还是毒瘤。

    我终于想到了dp(我恨dp)

    接下来考虑转移方程式 考虑第i个土块,对其有影响的数据只有前i个土块的高度,还有本土块的高度,所以: 我们用dp[i][j]将前i段变作不下降序列,且第j段道路的高度为j时的最小花费

    但是,j的枚举会把时间炸上天!!!!

    通过前面的结论,我们发现,最小的填补一定会在目标高度中出现,所以我们开另外一个数组,把高度存到里面,排序,从里面找一个合适的Ai,就省去了遍历1—100000000的时间

    继续方程式。写出来就是这样,前i个柱子最小(此为单调不递减)

    此题,洛谷数据过于划水以至于只考虑单增就可以过了。

    于是放代码(只放单增的了)

    #include<bits/stdc++.h>
    using namespace std;
    const int inf=0x7fffffff;
    const int maxn=2010;
    int n;
    int a[maxn],b[maxn];
    int dp[maxn][maxn];
    int main()
    {
        int ans=inf;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        scanf("%d",&a[i]),b[i]=a[i];
        sort(b+1,b+1+n);
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(j==1)//因为循环边界,所以当j==1我们要特判一发,把1拍到最低
                    dp[i][j]=dp[i-1][j]+abs(a[i]-b[j]);
                else
                    dp[i][j]=min(dp[i][j-1],dp[i-1][j]+abs(a[i] - b[j]));//拍土了
                if(i==n)
                    ans=min(dp[i][j],ans);
            }
        }
        printf("%d
    ",ans);
        return 0;
    }

     (膜拜一下隔壁dp神仙)

  • 相关阅读:
    前台线程与后台线程的区别
    触发器
    Asp.net AutopostBack 属性
    Spring实战拆书--SpringBean
    侣行APP
    用android去写一个小程序
    java如何使用JUnit进行单元测试
    JDK的安装与配置以及eclipse的使用
    软件工程第一次作业(1)
    软件工程第一次作业(2)
  • 原文地址:https://www.cnblogs.com/ajmddzp/p/11427387.html
Copyright © 2011-2022 走看看