zoukankan      html  css  js  c++  java
  • POJ 1390 Blocks (区间DP)

    Description

    Some of you may have played a game called 'Blocks'. There are n blocks in a row, each box has a color. Here is an example: Gold, Silver, Silver, Silver, Silver, Bronze, Bronze, Bronze, Gold. 
    The corresponding picture will be as shown below: 
     
    Figure 1

    If some adjacent boxes are all of the same color, and both the box to its left(if it exists) and its right(if it exists) are of some other color, we call it a 'box segment'. There are 4 box segments. That is: gold, silver, bronze, gold. There are 1, 4, 3, 1 box(es) in the segments respectively. 

    Every time, you can click a box, then the whole segment containing that box DISAPPEARS. If that segment is composed of k boxes, you will get k*k points. for example, if you click on a silver box, the silver segment disappears, you got 4*4=16 points. 

    Now let's look at the picture below: 
     
    Figure 2


    The first one is OPTIMAL. 

    Find the highest score you can get, given an initial state of this game. 

    Input

    The first line contains the number of tests t(1<=t<=15). Each case contains two lines. The first line contains an integer n(1<=n<=200), the number of boxes. The second line contains n integers, representing the colors of each box. The integers are in the range 1~n.

    Output

    For each test case, print the case number and the highest possible score.

    Sample Input

    2
    9
    1 2 2 2 2 3 3 3 1
    1
    1

    Sample Output

    Case 1: 29
    Case 2: 1

    思路:

    1. 将颜色相同又邻接的方块合并到一起, 成为一个 segment. 由得分的规则知, 一个 segment 同时消除一定比 segment 内部分成几个部分再消除得分高

    2. 设 i 表示 segment 的 index. 那么 color[i], len[i] 分别代表第 i 个 segment 的颜色和长度

    3. dp[i, j, k] 表示从第 i 到 第 j 个 segment, 并且第 j 个 segment 后面还有 k 个不与 j 相邻但颜色与 j 相同的方块数

    4. 当第 j 个 segment 与后面 k 个结合时, 那dp[i, j, k] = dp[i, j-1, 0] + (len[j]+k)^2

    5. 当第 j 个 segment 与前面的某段合并时, dp[i, j, k] = max(dp[i, j, k], dp[i, s, k+len[j]]+dp[s+1, j-1, 0])

     相当于先消除 [s+1, j-1] 这些方块

    6. 由 (5) 的状态转移方程可以看出, 有 max, 有枚举, 这是一个典型的记忆化搜索过程

    update 2014年3月15日15:31:20

    1.思考时应当考虑从后向前推

    代码: 

    #include <iostream>
    using namespace std;
    
    const int MAXN = 210;
    int testCase, N;
    int color[MAXN];
    int len[MAXN];
    int block[MAXN];
    int dp[MAXN][MAXN][MAXN];
    
    int solve_dp(int l, int r, int k) {
    	if(dp[l][r][k]) 
    		return dp[l][r][k];
    	if(l == r)
    		return dp[l][r][k] =(k+len[r])*(k+len[r]);
    	// 直接消除
    	//cout << solve_dp(l, r-1, 0) + (k+len[r])*(k+len[r]) << endl;
    	dp[l][r][k] = solve_dp(l, r-1, 0) + (k+len[r])*(k+len[r]);
    	// 先消除中间的, 合并 color[r], 在消除颜色为 r 的
    	for(int i = l; i < r; i++) {
    		if(color[i] == color[r])
    			dp[l][r][k] = max(dp[l][r][k], solve_dp(l, i, k+len[r]) + solve_dp(i+1, r-1, 0)); 
    	}
    	return dp[l][r][k];
    }
    int main() {
    	freopen("E:\Copy\test\in.txt", "r", stdin);
    	cin >> testCase;
    	int caseTh = 0;
    	while(testCase--) {
    		caseTh++;
    		cin >> N;
    		for(int i = 0; i < N ; i ++) {
    			cin >> block[i];
    		}
    		color[0] = block[0];
    		len[0] = 1;
    		int cursor = 0;
    		for(int i = 1; i < N; i ++) {
    			if(block[i] == block[i-1]) {
    				len[cursor]++;
    			}else{
    				cursor ++;
    				color[cursor] = block[i];
    				len[cursor] = 1;
    			}
    		}
    		memset(dp, 0, sizeof(dp));
    		printf("Case %d: %d
    ", caseTh, solve_dp(0, cursor, 0));
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    算法笔记 第3章 入门篇(1) 学习笔记
    算法笔记 上机训练实战指南 第3章 入门篇(1)--入门模拟 学习笔记 3.1简单模拟
    机器学习实战:基于Scikit-Learn和TensorFlow 第5章 支持向量机 学习笔记(硬间隔)
    机器学习实战:基于Scikit-Learn和TensorFlow 读书笔记 第6章 决策树
    算法笔记 第7章 提高篇(1)--数据结构专题(1) 学习笔记
    算法笔记 第6章 C++标准模版库(STL)介绍 学习笔记
    自然语言处理入门 何晗 读书笔记 第2章 词典分词
    自然语言处理入门 何晗 读书笔记 第1章 新手上路
    [ML]随机森林
    [ML]LightGBM论文理解
  • 原文地址:https://www.cnblogs.com/xinsheng/p/3452710.html
Copyright © 2011-2022 走看看