HNOI2008[玩具装箱]

动态规划,四边形不等式优化,这道题还可以斜率优化。

CODE:

/*

PROGRAM: $PROGRAM

AUTHOR: Su Jiao

DATE: 2010-5-29

DESCRIPTION:

湖南2008年省选 玩具装箱

*/

#include <stdio.h>

 

class Application

{

      FILE* in;

      FILE* out;

      static const int MAXN=50000;

      int N,L;

      int c[MAXN];

      void print_long_long_int(long long int number)

      {

           if (number>=10) print_long_long_int(number/10);

           fprintf(out,“%d”,number%10);

      }

      public:

      Application(const char* input=0,const char* output=0)

                        :in(input?fopen(input,“r”):stdin),

                         out(output?fopen(output,“w”):stdout)

      {

                         fscanf(in,“%d%d”,&N,&L);

                         for (int i=0;i<N;i++)

                             fscanf(in,“%d”,c+i);

      }

      ~Application()

      {

                    fclose(in);

                    fclose(out);

      }

      int run()

      {

          long long int sum[MAXN+1];

          sum[0]=0;

          for (int i=0;i<N;i++)

              sum[i+1]=sum[i]+c[i];

          long long int f[MAXN+1];

          /*

          f[0]=0;

          for (int i=1;i<=N;i++)

          {

              f[i]=1000000000000000000ll;

              for (int j=0;j<i;j++)

              {

                  long long int x=i-j-1+sum[i]-sum[j]-L;

                  x*=x;

                  if (f[i]>f[j]+x)

                     f[i]=f[j]+x;

              }

          }

          */

          int head,tail;

          int begin[MAXN+1],end[MAXN+1],best[MAXN+1];

          f[0]=0;

          head=tail=0;

          begin[tail]=0;

          end[tail]=N;

          best[tail]=0;

          for (int i=1;i<=N;i++)

          {

              while (end[head]<i) head++;

              int j=best[head];

              long long int x=i-j-1+sum[i]-sum[j]-L;

              f[i]=f[j]+x*x;

              #define value(i,j) \

                      (f[j]+(i-j-1+sum[i]-sum[j]-L)*(i-j-1+sum[i]-sum[j]-L))

              while (head<tail

                     &&value(begin[tail],best[tail])>=value(begin[tail],i))

                     end[tail-1]=end[tail],tail–;

              int l=begin[tail],r=end[tail]+1;

              while (l+1!=r)

              {

                    int mid=(l+r)>>1;

                    if (value(mid,best[tail])<value(mid,i)) l=mid;

                    else r=mid;

              }

              if (l+1<=end[tail])

              {

                 tail++;

                 begin[tail]=l+1;

                 end[tail]=end[tail-1];

                 best[tail]=i;

                 end[tail-1]=l;

              }

          }

          print_long_long_int(f[N]);

          fprintf(out,“\n”);

          return 0;

      }

};

 

int main()

{

    Application app;

    return app.run();

}

 

留下评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注