zoukankan      html  css  js  c++  java
  • POJ 1141 Brackets Sequence(区间DP, DP打印路径)

    Description

    We give the following inductive definition of a “regular brackets” sequence:

    • the empty sequence is a regular brackets sequence,
    • if s is a regular brackets sequence, then (s) and [s] are regular brackets sequences, and
    • if a and b are regular brackets sequences, then ab is a regular brackets sequence.
    • no other sequence is a regular brackets sequence

    For instance, all of the following character sequences are regular brackets sequences:

    (), [], (()), ()[], ()[()]

    while the following character sequences are not:

    (, ], )(, ([)], ([(]

    Given a brackets sequence of characters a1a2 … an, your goal is to find the length of the longest regular brackets sequence that is a subsequence of s. That is, you wish to find the largest m such that for indices i1i2, …, im where 1 ≤ i1 < i2 < … < im ≤ nai1ai2… aim is a regular brackets sequence.

    Given the initial sequence ([([]])], the longest regular brackets subsequence is [([])].

    Input

    The input test file will contain multiple test cases. Each input test case consists of a single line containing only the characters ()[, and ]; each input test will have length between 1 and 100, inclusive. The end-of-file is marked by a line containing the word “end” and should not be processed.

    Output

    For each input case, the program should print the length of the longest possible regular brackets subsequence on a single line.

    Sample Input

    ((()))
    ()()()
    ([]])
    )[)(
    ([][][)
    end

    Sample Output

    6
    6
    4
    0
    6

    思路:

    1. dp[i][j] 表示 子序列 [i, j] 之间的最小添加括号数

    2. dp[i][j] = min(dp[i][k], dp[k+1][j]) k = [i, j]

    3. choose[i][j] 表示在 dp[i][j] 中的那个位置切割比较合适, 合适的定义是 dp[i][j] > dp[i][k]+dp[k+1][j]

    4. 对 dp[i][j] 的计算, 第一种思路是记忆化搜索, 当时还没考虑到 choose 数组. 对于 choose 数组的求解, 记忆化搜索不能实现. 代码里提供的是基于递推的求解过程,  这种遍历方法我也曾做过, 叫做斜对角线更新, 具体是哪道题目也记不清了, blog 我是有写过的

    总结:

    1.区间 DP

    2. 这个地方 WA 了下, 起初写成 k<=j

    for(int k = i; k < j; k++) {
    	if(dp[i][j] > dp[i][k]+dp[k+1][j]) { // that's why/where need special judge
    	  choose[i][j] = k;
    	  dp[i][j] = dp[i][k]+dp[k+1][j];
    	}
    }
    

    update 2014年3月15日14:43:10

    3. 类似的题目有 Leetcode palindrome cut, 并且 palindrome cut 是在原始区间 DP 的基础上加上了一些优化. 矩阵乘法也算是区间 DP

    代码:

    #include <iostream>
    using namespace std;
    
    const int INF = 0X3F3F3F3F;
    const int MAXN = 110;
    int choose[MAXN][MAXN];
    int dp[MAXN][MAXN];
    char s[MAXN];
    
    void printPath(const int &i, const int &j) {
    	if(j < i)
    		return ;
    	if(i == j) {
    		if(s[i] == '(' || s[i] == ')') {
    			cout << "()";
    			return;
    		}else if(s[i] == '[' || s[i] == ']') {
    			cout << "[]";
    			return;
    		}
    	}
    	if(choose[i][j] == -1) { // 不需要切割
    		cout << s[i];
    		printPath(i+1, j-1);
    		cout << s[j];
    	}else{
    		int k = choose[i][j];
    		printPath(i, k);
    		printPath(k+1, j);
    	}
    }
    int main() {
    	//freopen("E:\Copy\ACM\测试用例\in.txt", "r", stdin);
    	gets(s);
    	int st = 0, ed = strlen(s);
    	memset(dp, 0x3F, sizeof(dp));
    	for(int i = st; i < ed; i ++)
    		dp[i][i] = 1, dp[i+1][i] = 0;
    	for(int p = 1; p < ed-st; p ++) {
    		for(int i = 0, j = i+p; j < ed; i++, j++) {
    			choose[i][j] = -1;
    			if((s[i] == '(' && s[j] == ')') || (s[i] == '[' && s[j] == ']')) {
    				dp[i][j] = min(dp[i][j], dp[i+1][j-1]); // 需要考虑 dp[j][i] = 0
    			}
    			for(int k = i; k < j; k++) {
    				if(dp[i][j] > dp[i][k]+dp[k+1][j]) { // that's why/where need special judge
    					choose[i][j] = k;
    					dp[i][j] = dp[i][k]+dp[k+1][j];
    				}
    			}
    		}
    	}
    	printPath(0, ed-1);
    	cout << endl;
    	return 0;
    }
    

      

  • 相关阅读:
    把C语言的指针按在地上摩擦!
    组合索引相关介绍
    ConcurrentModificationException异常
    chat和varchar的区别?
    二进制部署K8S集群(二十三)addons之安装部署dashboard
    二进制部署K8S集群(二十二)addons之安装部署ingress
    二进制部署K8S集群(二十一)addons之flanneld优化SNAT规则
    二进制部署K8S集群(二十)K8s服务暴露之NodePort型Service
    二进制部署K8S集群(十九)addons之安装部署coredns
    二进制部署K8S集群(十八)addons之flannel三种模型安装部署详解
  • 原文地址:https://www.cnblogs.com/xinsheng/p/3452828.html
Copyright © 2011-2022 走看看