区间DP | 洛谷 | P1040

版权声明:本文纯属作者口胡,欢迎转载 https://blog.csdn.net/TQCAI666/article/details/86476042

https://www.luogu.org/problemnew/show/P1040
f[i][j]视为 i 到 j 上的最大值, 计算规则依题意. 对于空结点表示1, 用f[i][j] , i>j来处理. 依据循环的边界条件, 只需要对f[i][i-1]以及f[N+1][N]做处理即可.
循环过程类似石子合并.

#include <bits/stdc++.h>
#define FF(a,b) for(int a=0;a<b;a++)
#define F(a,b) for(int a=1;a<=b;a++)
#define LEN 40
#define bug(x) cout<<#x<<"="<<x<<endl;

using namespace std;

int N;
int f[LEN][LEN];
int root[LEN][LEN];
int cnt=0;//空格计数

inline void print_num(int num){
    printf("%d",num);
    cnt++;
    if(cnt<N) putchar(' ');
}

void print(int l,int r){
    if(l>r) return;
    int m=root[l][r];
    print_num(m);
    if(l==r) return;
    print(l,m-1);
    print(m+1,r);

}

int main()
{
    freopen("./in","r",stdin);
    cin>>N;
    F(i,N){
        cin>>f[i][i];
        f[i][i-1]=1; //空结点为0
        root[i][i]=i;
    }
    f[N+1][N]=1;
    for(int d=1;d<N;d++){//间隔
        for(int i=1;i+d<=N;i++){//开始
            int j=i+d;//结束
            root[i][j]=i;
            f[i][j]=f[i][i]+f[i+1][j];
            for(int k=i+1;k<=j;k++){ //分割
                int tmp_fij=f[k][k]+f[i][k-1]*f[k+1][j];
                if(tmp_fij>f[i][j]){
                    f[i][j]=tmp_fij;
                    root[i][j]=k;
                }
            }
        }
    }
    cout<<f[1][N]<<endl;
    print(1,N);
    return 0;
}



猜你喜欢

转载自blog.csdn.net/TQCAI666/article/details/86476042
今日推荐