• CDOJ 594:我要长高 单调队列优化DP


    我要长高

    题目链接:

    http://www.acm.uestc.edu.cn/#/problem/show/594

    题意:

    中文

    题解:

    可以发现数据小些的话是很简单的   dp[i][j](第 i 个人身高为 j 的最小花费)=min(dp[i-1][k]+abs(k-j)*C)+(h[i]-j)^2

    由于数据略大,会发现时间复杂度大约是1e9的,由于状态转移方程满足用单调队列优化的条件,直接用单调队列优化就行了

    (其实只需要用个值记录下动态的最小值就好了=_=)

    代码

    #include<stdio.h>
    #define mmin(a,b) (a<b?a:b)
    const int M=1e2+1;
    int dp[2][M],Que[101];
    const int inf=2e9+1;
    void solve()
    {
      int n,c,h,tail,head,ch=0;
      while(~scanf("%d%d",&n,&c))
      {
        scanf("%d",&h);
        for(int i=0;i<=100;++i)
        dp[ch][i]=i<h?inf:(h-i)*(h-i);
        for(int i=1;i<n;++i)
        {
          ch=1-ch;
          scanf("%d",&h);
          tail=0,head=1;
          for(int j=0;j<=100;++j)//前一人身高小于j 当前人身高等于 j
          {
            while(dp[1-ch][j]-j*c<=Que[tail]&&tail>=head)--tail;//这一部分也可以改为 S=min(S,dp[1-ch][j]-j*c) 0.0就不需要开队列了
            Que[++tail]=dp[1-ch][j]-j*c;//与0的差值
            if(j<h)dp[ch][j]=inf;
            else dp[ch][j]=Que[head]+(h-j)*(h-j)+j*c;
          }
          tail=0,head=1;
          for(int j=100;j>=0;--j)
          {
            while(dp[1-ch][j]+j*c<=Que[tail]&&tail>=head)--tail;
            Que[++tail]=dp[1-ch][j]+j*c;
            if(j>=h)dp[ch][j]=mmin(dp[ch][j],Que[head]+(h-j)*(h-j)-j*c);
          }      
        }
        int res=dp[ch][h];
        for(int i=h+1;i<=100;++i)
        if(dp[ch][i]<res)res=dp[ch][i];
        printf("%d ",res);
      }
    }


    int main()
    {
      solve();
      return 0;
    }

     
     
  • 相关阅读:
    System.web和System.WebServer
    Clone Detective java home
    2008年国外最佳Web设计/开发技巧、脚本及资源总结
    Multiview + UserControl 中UserControl如何判断首次执行
    .NET必看的几个网站
    深入剖析ASP.NET的编译原理之一:动态编译(Dynamical Compilation)(转)
    SQL Server 阻止了对组件 \'Ad Hoc Distributed Queries\' 的访问
    SQL SERVER 建表的限制
    dll文件
    com组件ConvertStringToBSTR(转)
  • 原文地址:https://www.cnblogs.com/kiuhghcsc/p/6020721.html
Copyright © 2020-2023  润新知