區間DP | 洛谷 | P1040
阿新 • • 發佈:2019-01-14
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;
}