UVA10559 Blocks(区间dp)

有n个带有颜色的方块,没消除一段长度为x的连续的相同颜色的方块可以得到x^2的分数,让你用一种最优的顺序消除所有方块使得得分最多。

输入格式 第一行包含测试的次数t(1≤t≤15) 每个案例包含两行。第一行包含整数n(1≤n≤200),即框数。第二行包含n个数,代表每个盒子的颜色。数字的大小1~n内。

Solution

n比较小,所以我们要用n^3的dp。

我们设dp[i][j][k]表示从i缩到j,j要和j后面的k个格子缩到一起能获得的最大分数。

转移的话枚举断点,如果有一个点和j相等,就把k向前传递,否侧向后传递。

Code

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int x,dp[309][309][309],a[309],b[309],n,tot,t,p; 
int dfs(int i,int j,int s){   
    if(dp[i][j][s])return dp[i][j][s];
    if(i>j)return 0;
    if(i==j)return dp[i][j][s]=(b[j]+s)*(b[j]+s);
    for(int k=i;k<j;++k)
      if(a[k]==a[j])
        dp[i][j][s]=max(dp[i][j][s],dfs(i,k,s+b[j])+dfs(k+1,j-1,0));
      else dp[i][j][s]=max(dp[i][j][s],dfs(i,k,0)+dfs(k+1,j,s));
    return dp[i][j][s];
}
int main(){
    cin>>t;
    while(t--){
    p++;
    cin>>n;a[0]=-99;tot=0;
    memset(dp,0,sizeof(dp));
    for(int i=1;i<=n;++i){
      scanf("%d",&x); 
      if(x==a[tot])b[tot]++;
      else a[++tot]=x,b[tot]=1;
    }
    cout<<"Case "<<p<<": "<<dfs(1,tot,0)<<endl;
    }
    return 0;
}
posted @ 2018-10-24 08:57  comld  阅读(160)  评论(0编辑  收藏  举报