区间DP复习篇

区间DP复习

区间DP的套路性还是很强的。一般就是转移方程都是f[l,r]或者有时候区间状态不好表示的时候需要用状压也就是f[l,r,sates]。(后者应该属于比较难的那种了)
区间DP一般我们的步骤就是
1,枚举区间长度,
2,枚举左端点,同时枚举右端点
3,枚举区间内的中间节点(会造成影响的last点)
4,根据状态转移方程式来进行转移。有时候边状态转移的时候还需要记录信息。
以加分二叉树为例,我们记录一个二叉树的区间最大值的同时还需要记录他的根。

#include <bits/stdc++.h>
using namespace std;
const int N=100+7;
int a[N],f[N][N];
int rt[N][N];
void print(int l,int r)
{
    if(l>r) return ;
    printf("%d ",rt[l][r]);
    int root=rt[l][r];
    print(l,root-1);
    print(root+1,r);
}
int main()
{
    int n; cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=n;i++){
        for(int j=1;j+i-1<=n;j++){
            int l=j,r=j+i-1;
            for(int k=l;k<=r;k++){
                int left,right;
                if(i==1){
                    rt[l][r]=l;
                    f[l][r]=a[l];
                }
                else {
                    if (l == k) {
                        left = 1;
                    } else {
                        left = f[l][k-1];
                    }
                    if (r == k) {
                        right = 1;
                    } else {
                        right = f[k+1][r];
                    }
                    int score = left*right + a[k];
                    if(score>f[l][r]){
                        f[l][r]=score;
                        rt[l][r]=k;
                    }
                }
            }
        }
    }
    cout<<f[1][n]<<endl;
    print(1,n);
}
发布了181 篇原创文章 · 获赞 10 · 访问量 5096

猜你喜欢

转载自blog.csdn.net/weixin_42979819/article/details/104124196