题解 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;
}