dp[le][ri][k]表示区间[le,ri]并且右边还有k个和 ri位置相同颜色的方块 的最优解。
转移时间O(n),状态O(n^3),时间复杂度O(n^4)(一般来说n为200,这样可能会超时),用记忆化搜索很多状态不会达到,可过。
/**==========================================
* This is a solution for ACM/ICPC problem
*
* @source:
* @type:
* @author: wust_ysk
* @blog: http://blog.csdn.net/yskyskyer123
* @email: 2530094312@qq.com
*===========================================*/
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#define sqr(x) ((x)*(x))
using namespace std;
typedef long long ll;
const int INF =0x3f3f3f3f;
const int maxn=200 ;
int n;
int a[maxn+3],dp[maxn+3][maxn+3][maxn+3];
int get(int le,int ri,int k)
{
return sqr(ri-le+1+k);
}
int DP(int le,int ri,int k)
{
int &ans=dp[le][ri][k];
if(~ans) return ans;
if(le>ri) return ans=0;
ans=0;
int p;
for(p=ri;p-1>=le&&a[p-1]==a[p];p--);
ans=max(ans,DP(le,p-1,0)+get(p,ri,k) );
for(int q=le;q<p-1;q++) if(a[q]==a[ri]&&a[q]!=a[q+1])
{
ans=max(ans,DP(q+1,p-1,0)+DP(le,q, k+ri-p+1 ) );
}
return ans;
}
int main()
{
int T,kase=0;scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
memset(dp,-1,sizeof dp);
printf("Case %d: %d\n",++kase,DP(1,n,0));
}
return 0;
}
总结:
记忆化搜索和递推的优劣
我不知道递推求解会不会超时。
每次转移都是进那么一步,不好转移时加状态,解法都是很简单的,就看你能否想到。