1. 程式人生 > >區間DP | 洛谷 | P1040

區間DP | 洛谷 | P1040

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; }