• 解题:NOI 2009 诗人小G


    题面

    今天考试考了,于是开始糊学决策单调性DP

    这是一个完全不会优化DP的人

    决策单调性DP的一种优化方法是用单调队列优化

    存下{左端点l,右端点r,最优决策点p}的三元组,按照单调队列的通常操作来说:

    (0.初始化,将整个序列丢进去)

    1.弹队头:弹掉所有不合法的三元组(r<i的)

    2.求答案,同时更新队头的左端点

    3.弹队尾:

    ①如果队尾的决策点不如i优,说明队尾这整个三元组当前的决策点太靠前了,直接弹掉

    ②当弹不掉时,根据决策单调性,队尾这个三元组后面的一部分决策点是i,前面的不是,二分出这个位置来修改。当然如果你发现事实上决策点在l就可以直接把整个都弹了=。=

    4.入队(没啥可说的)

     1 #include<cmath>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define lli long long
     6 #define double long double
     7 using namespace std;
     8 const int N=100005;
     9 const lli inf=1e18;
    10 struct a
    11 {
    12     int l,r,p;
    13 }que[N];
    14 int T,n,m,k,f,b,top,pre[N],stk[N]; 
    15 lli len[N]; double dp[N]; char str[N][32];
    16 double Qpow(double x,int k)
    17 {
    18     if(k==1) return x;
    19     double tmp=Qpow(x,k/2);
    20     return k%2?tmp*tmp*x:tmp*tmp;
    21 }
    22 double Calc(int a,int b)
    23 {
    24     return dp[b]+Qpow(fabs(len[a]-len[b]-m-1),k);
    25 }
    26 int main()
    27 { 
    28     scanf("%d",&T);
    29     while(T--)
    30     {
    31         scanf("%d%d%d",&n,&m,&k);
    32         for(int i=1;i<=n;i++)
    33         {
    34             scanf("%s",str[i]+1);
    35             len[i]=len[i-1]+strlen(str[i]+1)+1;
    36         }
    37         que[f=b=0]=(a){1,n,0};
    38         for(int i=1;i<=n;i++)
    39         {
    40             while(f<b&&que[f].r<i) f++;
    41             int pt=que[f].p; que[f].l++;
    42             dp[i]=Calc(i,pt),pre[i]=pt;
    43             while(f<b&&Calc(que[b].l,que[b].p)>=Calc(que[b].l,i)) b--;
    44             int lp=que[b].l,rp=que[b].r,ps=rp+1;
    45             while(lp<=rp)
    46             {
    47                 int mid=(lp+rp)/2;
    48                 if(Calc(mid,i)<=Calc(mid,que[b].p)) rp=mid-1,ps=mid;
    49                 else lp=mid+1;
    50             }
    51             (ps==que[b].l)?b--:que[b].r=ps-1;
    52             if(ps<=n) que[++b]=(a){ps,n,i};
    53         }
    54         if(dp[n]>inf) puts("Too hard to arrange");
    55         else
    56         {
    57             printf("%lld
    ",(lli)dp[n]),top=0;
    58             for(int i=n;i;i=pre[i]) stk[++top]=i; stk[++top]=0; 
    59             for(int i=top;i;i--)
    60                 for(int j=stk[i+1]+1;j<=stk[i];j++)
    61                 {
    62                     printf("%s",str[j]+1);
    63                     j==stk[i]?puts(""):putchar(' ');
    64                 }
    65         }
    66         puts("--------------------");
    67     }
    68     return 0;
    69 }
    View Code
  • 相关阅读:
    SERVER2008下安装SQL SERVER 2005出现IIS功能要求 警告解决方案
    转:Windows Server 2008 IIS 7.0 图文安装详解
    (转)程序集System.Web.DataVisualization无法加载的解决方法
    C++ Primer Plus 读书笔记(第1, 2章)
    寒假就这样来了
    C++ Primer Plus 读书笔记(第8、9章)
    C++ Primer Plus 读书笔记(第6、7章)
    POJ1947 Rebuilding Roads 树形DP
    C++ Primer Plus 读书笔记(第4、5章)
    POJ2754 Similarity of necklaces 2 区间取下界操作+DP
  • 原文地址:https://www.cnblogs.com/ydnhaha/p/10458376.html
Copyright © 2020-2023  润新知