习题: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;
}
posted @ 2020-07-29 09:51  loney_s  阅读(92)  评论(0)    收藏  举报