题解:CF1312E Array Shrinking
不同于其它题解的 dp 做法。
考虑状态
设
每次遍历到一个新的数
- 不与前面的数合并,则
dp_{i,a_i}=1 ,mn_{i}=ans_{i,a_i}=mn_{i-1}+1 。 - 与前面的数合并:
- 首先,设
x=a_i,l=i-1 。 - 如果
dp_{l,x} 不为0 ,即状态(l,x) 可达,因此可以将现在的数x 和前面的状态l,x 最右边的x 合并。现在的x 变为x+1 ,l 变为l-dp_{l,x} ,并继续重复这一步,尝试与更前面的数合并(并分别把答案保存在dp_{i,x} 和ans_{i,x} 中),直到dp_{l,x}=0 ,则不能继续合并。
- 首先,设
最后输出
#include<bits/stdc++.h>
using namespace std;
const int N=505;
int a[N];
int dp[N][N<<1],ans[N][N<<1],mn[N];
int main(){
ios::sync_with_stdio(0);cin.tie(0);
int n;cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++){
int x=a[i];
dp[i][x]=1;
mn[i]=ans[i][x]=mn[i-1]+1;
int l=i-1;
while(dp[l][x]){
dp[i][x+1]=i-(l-dp[l][x]);
ans[i][x+1]=ans[l][x];
mn[i]=min(mn[i],ans[i][x+1]);
l-=dp[l][x];
x++;
}
}
cout<<mn[n];
return 0;
}