zoukankan      html  css  js  c++  java
  • [poj1390]Blocks(方块消除)

    题目大意:给定一序列,可点击某一位置消除与其相邻且相同的方块,得分为$len*len$,求最大得分。

    解题关键:关键是状态的构造,首先离散化一下,令$dp[i][j][k]$表示序列$i-j$且后面有$k$个与该序列最后位置相同的元素,

    则$dp[i][j][k]$可以由两种情况转化而来,

    1、最后一部分自己消除 $dp[i][j][k]=dp[i][j-1][0]+(k+len[j])*(k+len[j])$

    2、最后一部分和该序列中前面的某一部分消除,假设坐标pos与r颜色相同 $dp[i][j][k]=dp[i][pos][k+len[j]]+dp[pos+1][j-1][0]$

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #include<iostream>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    int t,n,dp[202][202][202],a[202],len[202],clr[202],num;
    int dfs(int l,int r,int k){
        if(l>r) return 0;
        if(dp[l][r][k]) return dp[l][r][k];
        dp[l][r][k]=dfs(l,r-1,0)+(k+len[r])*(k+len[r]);
        for(int i=l;i<r;i++){
            if(clr[i]==clr[r]) dp[l][r][k]=max(dp[l][r][k],dfs(l,i,k+len[r])+dfs(i+1,r-1,0));
        }
        return dp[l][r][k];
    }
    int main(){
        scanf("%d",&t);
        for(int ca=1;ca<=t;ca++){
            memset(dp,0,sizeof dp);
            memset(len, 0, sizeof len);
            num=0;
            scanf("%d",&n);
            for(int i=1;i<=n;i++) scanf("%d",a+i);
            for(int i=0;i<=n;i++){
                if(a[i]!=a[i-1]) clr[++num]=a[i],len[num]=1;
                else len[num]++;
            }
            int ans=dfs(1,num,0);
            printf("Case %d: %d
    ",ca,ans);
        }
        return 0;
    }
  • 相关阅读:
    写代码随想
    学生管理系统
    自定义栈
    位运算符加密
    自定义Vector
    二叉树排序
    双向循环链表
    双向链表
    加载properties文件
    通讯录
  • 原文地址:https://www.cnblogs.com/elpsycongroo/p/7812183.html
Copyright © 2011-2022 走看看