习题:Array Shrinking(DP)
题目
思路
考虑到一个区间如果能缩成一个点,那么这个点的值一定是确定的
所以我们设\(dp[l][r]\)为区间\(l,r\)最终缩成的点的值
如果不能缩成一个点,那么\(dp[l][r]=0\)
\(dp[l][r]\)的转移枚举一个分界点即可
之后就是一个划分区间的问题
按照套路,设\(f[i]\)为前i个数构造的数组剩余的最小值
\(f[i]=min\{f[j]+1[dp[j+1][i]!=0]\}\)
代码
#include<iostream>
#include<cstring>
using namespace std;
int n;
int a[505];
int f[505][505];
/*
区间l~r缩成一个点之后的数是多少
如果不能缩成一个点,值为0
*/
int dp[505];//前i个数的最小长度
int dfs1(int l,int r)
{
if(f[l][r]!=-1)
return f[l][r];
for(int i=l;i<r;i++)
{
if(dfs1(l,i)==dfs1(i+1,r)&&dfs1(l,i)!=0)
{
f[l][r]=f[l][i]+1;
return f[l][r];
}
}
f[l][r]=0;
return 0;
}
int main()
{
ios::sync_with_stdio(false);
memset(f,-1,sizeof(f));
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
f[i][i]=a[i];
}
dfs1(1,n);
for(int i=1;i<=n;i++)
{
dp[i]=i;
for(int j=0;j<i;j++)
if(f[j+1][i]!=0)
dp[i]=min(dp[i],dp[j]+1);
}
cout<<dp[n];
return 0;
}

浙公网安备 33010602011771号