E - Array Shrinking区间dp||dp
题:https://codeforces.com/contest/1312/problem/E
题意:对于一个序列可以选相邻俩个数进行合并成其数+1,问合成后的最小序列长度是多少
分析1:设f[][]表示区间[i,j]区间向前合成的最小长度,简单的模拟一下即可求出,最后dp往后考虑合并
#include<bits/stdc++.h> using namespace std; const int M=1e3+3; int sta[M],f[M][M],a[M],ans[M]; int main(){ int n; ios::sync_with_stdio(false); cin.tie(0); cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; for(int i=1;i<=n;i++){ int top=0; for(int j=i;j<=n;j++){ int x=a[j]; while(top&&sta[top]==x) top--,x++; sta[++top]=x; f[i][j]=top; } } memset(ans,0x3f,sizeof(ans)); ans[0]=0; for(int i=1;i<=n;i++) for(int j=0;j<i;j++) ans[i]=min(ans[i],ans[j]+f[j+1][i]); cout<<ans[n]<<endl; return 0; }
分析2:dp区间长度
#include<bits/stdc++.h> using namespace std; const int M=1e3+3; int sta[M],f[M][M],a[M],ans[M]; int main(){ int n; ios::sync_with_stdio(false); cin.tie(0); cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; for(int i=1;i<=n;i++){ int top=0; for(int j=i;j<=n;j++){ int x=a[j]; while(top&&sta[top]==x) top--,x++; sta[++top]=x; f[i][j]=top; } } memset(ans,0x3f,sizeof(ans)); ans[0]=0; for(int i=1;i<=n;i++) for(int j=0;j<i;j++) ans[i]=min(ans[i],ans[j]+f[j+1][i]); cout<<ans[n]<<endl; return 0; }