uva10559 Blocks(DP 费用提前)

该题的难点在于费用的计算,需考虑未来能转移到的所有状态

用dp[l][r][next]表示l到r之间以及r之后与r同色的所有next个方块的最大费用和

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int t,n,a[202],k,cnt;
int dp[202][202][202];
struct block{
    int x,c;
    block(){}
    block(int x,int c):x(x),c(c){}
}b[202];
void init(){
    k=1,cnt=1;
    for(int i=1;i<n;i++){
        if(a[i]==a[i-1]) cnt++;
        else{
            b[k++]=block(cnt,a[i-1]);
            cnt=1;
        }
    }
    b[k++]=block(cnt,a[n-1]);
}
int DP(int l,int r,int next){
    if(l>=r) return next*next;
    if(dp[l][r][next]!=-1) return dp[l][r][next];
    int ret=DP(l,r-1,b[r-1].x)+next*next;
    for(int i=r-1;i>=l;i--){
        if(b[i].c==b[r].c){
            ret=max(ret,DP(l,i,next+b[i].x)+DP(i+1,r-1,b[r-1].x));
        }
    }
    //cout<<l<<" "<<r<<" "<<next<<" "<<ret<<endl;
    return dp[l][r][next]=ret;
}
int gao(){
    memset(dp,-1,sizeof dp);
    return DP(1,k-1,b[k-1].x);
}
int main(){
    scanf("%d",&t);
    for(int ca=1;ca<=t;ca++){
        scanf("%d",&n);
        for(int i=0;i<n;i++) scanf("%d",&a[i]);
        init();
        printf("Case %d: %d
",ca,gao());
    }
    return 0;
}
uva10559
原文地址:https://www.cnblogs.com/wonderzy/p/3540671.html