Luogu-P2627 修剪草坪

£可爱£侵袭症+ 提交于 2019-11-27 12:59:05

 

题目

题目链接

 

 

测试得分:  100

 

 

 

主要算法 :  单调队列优化DP

 

 

题干:

  单调队列优化DP板子

 分析

  单调队列优化DP定长连续区间最值问题模型

  代码

  70分朴素DP

#include<stdio.h>  #include<stdlib.h>  #define FORa(i,s,e) for(int i=s;i<=e;i++)  #define FORs(i,s,e) for(int i=s;i>=e;i--)  #define LL long long   #define gc getchar()//pa==pb&&(pb=(pa=buf)+fread(buf,1,100000,stdin),stdin)?EOF:*pa++  #define File(name) freopen(name".in","r",stdin);freopen(name".out","w",stdout);    using namespace std;  char buf[100000],*pa,*pb;  inline int read();      const int N=1e6;  int n,k;  LL sum[N+1],f[N+1][2];   f[i][1]代表从1-i这段区间,i这个位置的奶牛选取的效率最大值  f[i][0]代表从1-i这段区间,i这个位置的奶牛不选取的效率最大值       inline LL max(LL fa,LL fb){return fa>fb?fa:fb;}  int main()  {      n=read(),k=read();      FORa(i,1,n) sum[i]=read(),sum[i]+=sum[i-1];      FORa(i,1,n)      {          f[i][0]=max(f[i-1][0],f[i-1][1]); //状态转移           FORa(j,i-k,i-1) f[i][1]=max(f[i][1],sum[i]-sum[j]+f[j][0]);      }      printf("%lld",max(f[n][0],f[n][1]));      return 0;  }  inline int read()  {      register char c(gc);register int f(1),x(0);      while(c<'0'||c>'9') f=c=='-'?-1:1,c=gc;      while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=gc;      return x*f;  }

  100分单调队列优化DP

#include<stdio.h>  #include<stdlib.h>  #define FORa(i,s,e) for(int i=s;i<=e;i++)  #define FORs(i,s,e) for(int i=s;i>=e;i--)  #define LL long long   #define gc getchar()//pa==pb&&(pb=(pa=buf)+fread(buf,1,100000,stdin),stdin)?EOF:*pa++  #define File(name) freopen(name".in","r",stdin);freopen(name".out","w",stdout);    using namespace std;  char buf[100000],*pa,*pb;  inline int read();      const int N=1e6;  int n,k;  LL sum[N+1],f[N+1][2];     int num[N+1],head=1,tail=0;  inline LL max(LL fa,LL fb){return fa>fb?fa:fb;}  int main()  {      n=read(),k=read();      FORa(i,1,n) sum[i]=read(),sum[i]+=sum[i-1];      FORa(i,1,n)      {          f[i][0]=max(f[i-1][0],f[i-1][1]);          while(head<=tail&&f[num[tail]-1][0]-sum[num[tail]-1]<f[i-1][0]-sum[i-1]) tail--;          num[++tail]=i;          while(head<tail&&num[head]<i-k+1) head++;          f[i][1]=f[num[head]-1][0]-sum[num[head]-1]+sum[i];      }      printf("%lld",max(f[n][0],f[n][1]));      return 0;  }  inline int read()  {      register char c(gc);register int f(1),x(0);      while(c<'0'||c>'9') f=c=='-'?-1:1,c=gc;      while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=gc;      return x*f;  }

总结:

   确定动规模型

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!