题解 P3146 【[USACO16OPEN]248】

· · 题解

正确的区间dp。

复杂度有点大,按理说常数会t,结果不开o2可以过,开了跑飞快..

显然一个区间的合并不一定是越大越有利,所以用(假的)dp存对于一个区间可以达到的值,用来更新大区间的值。

所以转移方程为:if(f[l][j-l][s]&&f[j+1][r-j-1][s])f[l][k][s+1]=1;

表示当组成此区间两个分区间都拥有同一个数时,这个区间的这个数加一即可被构成,然后递推到最后的大区间得到所有可取得的值,用一个变量存储最大构成值。

#include<iostream>
#include<cstdio>
using namespace std;
int n,x,ans;
bool f[255][255][45];
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>x;f[i][0][x]=1;ans=max(ans,x); 
     } 
    for(int k=1;k<n;k++)
    {
        for(int i=1;i+k<=n;i++)
        {
            int l=i,r=i+k;
            for(int j=l;j<r;j++)
            {
                for(int s=1;s<=40;s++)
                {
                if(f[l][j-l][s]&&f[j+1][r-j-1][s])f[l][k][s+1]=1;
                if(f[l][k][s+1])ans=max(ans,s+1);
            }
            }
        }
    }
    cout<<ans<<endl;
    return 0;
 }