如何看出是区间dp和线性dp,看其次始状态,即第二个状态

次始边界:初始状态的下一个状态
 以此题为例:
  区间dp:
    初始状态:拿完m-1个元素时,剩下最后一个元素,可以是任意一个
    次始状态:拿完m-2个元素时,剩下两个元素,可以是任意两个(题目限制只能是连续的两个)
  若是线性dp:
    初始状态:拿完m-1个元素时,剩下最后一个元素只能是第一个,即a[1]
    次始状态:拿完m-2个元素时,次始状态为a[2]

斜体部分是废话,不重要,不要看,不舍得删
看其初始边界
线性dp和区间dp的区别:

  • 线性dp:只能在队尾加元素,状态只能由上一层线性递推*
  • 区间dp:能在队首或队尾加元素,状态是由小区间推到大区间*
  • 此题为例:*
  • 区间dp:拿完m-1个元素时,剩下最后一个元素,可以是任意一个,即它的初始状态是任意一个元素*
  • 若是线性dp则拿完m-1个元素时,剩下最后一个元素只能是第一个,即它的初始状态是第一个元素*

题目分析:其每一行独立操作,互不影响,仅仅只要加上每一行的得分即可,所以可以将其每行分开来看
因其操作在首或尾拿数字,所以每次减小的是区间长度,反过来看是区间长度逐渐增加

include<bits/stdc++.h>

using namespace std;
namespace{
template
inline void read(T &s){
T f=1;s=0;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar()) s=(s<<1)+(s<<3)+(ch^48);
s=f;
}
}
#define ll long long
int n,m;
int a[85];
*
int128 ans;
__int128 f[85][85];
inline void write(int128 x){
if(x<0){putchar('-');x=-x;}
if(x>9) write(x/10);
putchar(x%10+'0');
}
int main(){
read(n);read(m);
int t=n;
while(t--){
for(int i=1;i<=m;++i) read(a[i]);
memset(f,0,sizeof(f));
for(int j=1;j<=m;++j){
for(int i=j;i;--i){
**int128 k=m-j+i; //k=m-(j-i)
__int128 z=((
int128)1<<k);
f[i][j]=max(f[i+1][j]+za[i],f[i][j-1]+za[j]);
}
}
ans+=f[1][m];
}
write(ans);
return 0;
}

//此题之前做过,也写过题解,再写一遍,两篇的侧重点不同

全部评论

相关推荐

想玩飞盘的菠萝蜜在春...:上交✌🏻也拒?
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务