zoukankan      html  css  js  c++  java
  • UVA 10599 Blocks 解题报告 (动态规划)

    UVA-10599 Blocks

    题意

    (n) 个有颜色的方块 (( n le 200)).

    每次可以把任意 (x) 个连续的同色方块消除, 得到的收益为 (x^2).

    求把所有方块消去后的最大收益.

    思路

    一道非常巧妙的 dp 状态设计题.


    这题的暴力除了搜索以外似乎没有什么想法,

    因为有些方块在初始序列中并不在一起, 但它们又可以在同一时刻消去, 用一般的区间 dp 的话肯定不行.


    那归根到底, 不好处理的原因就是我们很难确定要把哪几个方块一起消去, 那我们不妨把它设计进 dp 状态里.

    我们就以一个区间右端点的方块颜色为准, 钦定它右边的 (k) 方块和它一起消去,

    即, 设 (f[i][j][k]) 为消去区间 (i,j) 内的方块, 并且方块 (j) 一定要和它右边的 (k) 个同色方块 (不包括 (j)) 一起消去时获得的收益.

    考虑转移, 我们可以把这 (k+1) 个方块直接消去, 或者在 ([i,j)) 中再枚举一个与 (j) 同色的方块, 把它们一起删去, 所以

    1. (f[i][j][k]=f[i][j-1][0]+(k+1)^2)
    2. (f[i][j][k]=max{f[i][p][k+1] + f[p+1][j-1][0]}), 且 (p in [i,j), col[p]==col[j])

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int _=200+7;
    int T,n,col[_],pre[_],lst[_],f[_][_][_];
    void upd(int &x,int y){ x=max(x,y); }
    int main(){
      //freopen("x.in","r",stdin);
      cin>>T;
      for(int t=1;t<=T;t++){
        scanf("%d",&n);
        memset(f,0,sizeof(f));
        memset(lst,0,sizeof(lst));
        for(int i=1;i<=n;i++)
          scanf("%d",&col[i]);
        for(int i=1;i<=n;i++){
          pre[i]=lst[col[i]];
          lst[col[i]]=i;
        }
        for(int l=1;l<=n;l++){
          for(int i=1;i+l-1<=n;i++){
    	int j=i+l-1;
    	for(int k=0;k<=n;k++){
    	  upd(f[i][j][k],f[i][j-1][0]+(k+1)*(k+1));
    	  int p=pre[j];
    	  while(p>=i){
    	    upd(f[i][j][k],f[i][p][k+1]+f[p+1][j-1][0]);
    	    p=pre[p];
    	  }
    	}
          }
        }
        printf("Case %d: %d
    ",t,f[1][n][0]);
      }
      return 0;
    }
    
    
  • 相关阅读:
    七-八章学习笔记
    Linux基础学习截图
    20191221第十章读书笔记
    第九章读书笔记
    20191221读书笔记
    缓冲区溢出
    团队作业(二):需求分析
    2019-2020-1 20191319 《信息安全专业导论》第十二周学习总结
    2019-2020-1 20191319 《信息安全专业导论》第十一周学习总结
    2019-2020-1 20191319 《信息安全专业导论》第十周学习总结
  • 原文地址:https://www.cnblogs.com/BruceW/p/12180809.html
Copyright © 2011-2022 走看看