洛谷 P3146 [USACO16OPEN]248 G(区间dp)
传送门
解题思路
用dp[i][j]表示dp[i][j]能否合成一个数,负无穷表示合不成,否则即为合成的数。
然后枚举k,很显然,如果dp[i][k]==dp[k+1][j],dp[i][j]就可以从前面两个转化过来。
最后对所有的任意长度的区间取一个max。
AC代码
1 #include<iostream> 2 #include<algorithm> 3 #include<cmath> 4 #include<cstdio> 5 #include<cstring> 6 using namespace std; 7 const int maxn=250; 8 int n,a[maxn],dp[maxn][maxn],ans; 9 int main() 10 { 11 cin>>n; 12 memset(dp,-0x3f,sizeof(dp)); 13 for(int i=1;i<=n;i++) cin>>a[i]; 14 for(int i=1;i<=n;i++) dp[i][i]=a[i]; 15 for(int len=2;len<=n;len++){ 16 for(int i=1;i<=n;i++){ 17 int j=i+len-1; 18 if(j>n) break; 19 for(int k=i;k<j;k++){ 20 if(dp[i][k]==dp[k+1][j])dp[i][j]=max(dp[i][j],dp[i][k]+1); 21 } 22 } 23 } 24 for(int i=1;i<=n;i++) 25 for(int j=1;j<=n;j++) ans=max(ans,dp[i][j]); 26 cout<<ans; 27 return 0; 28 }