• Week12 作业 D


    题目描述:

    一串包括( 、) 、[ 、]的括号序列,找出一个最长的子序列,使这个子序列是一个合法的括号序列,输出最长的子序列的长度

    思路:

    定义状态:F[i][j]表示子串s[i...j]能得到的最长序列

    状态转移:F[i][j]=max{ F[i][k]+F[k+1][j] , i<=k<j } ,如果s[i]和s[j]匹配,则还应有F[i][j]=max{ f[i][j] , f[i+1][j-1]+2 }

    边界条件:F[i][i]=0

    答案:F[0][N-1](字符串从0开始编号)

    代码:

    记忆化搜索

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <cstring>
     4 #include <algorithm>
     5 #include <string>
     6 using namespace std;
     7 const int MAXN = 105;
     8 int f[MAXN][MAXN];
     9 bool vis[MAXN][MAXN];
    10 string s;
    11 int dp(int i, int j)
    12 {
    13     if (i == j) return f[i][j] = 0;
    14     if (vis[i][j]) return f[i][j];
    15     vis[i][j] = 1;
    16     if ((s[i] == '(' && s[j] == ')') || (s[i] == '[' && s[j] == ']'))
    17         f[i][j] = dp(i + 1, j - 1) + 2;
    18     for (int k = i; k <= j - 1; k++)
    19         f[i][j] = max(f[i][j], dp(i, k) + dp(k + 1, j));
    20     return f[i][j];
    21 }
    22 int main()
    23 {
    24     while (cin >> s)
    25     {
    26         if (s[0] == 'e') break;
    27         memset(f, 0, sizeof(f));
    28         memset(vis, 0, sizeof(vis));
    29         int N = s.size();
    30         cout << dp(0, N-1) << endl;
    31     }
    32     return 0;
    33 }
    View Code

     考虑编写递推的实现形式:发现记忆化搜索的过程中,子问题的区间长度,是比当前问题要小的,所以我们可以枚举区间长度,来顺序递推

    确定了计算顺序,就能保证子问题一定先被求解完,就可以安心递推了

    递推(确实比记忆化快)

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <string>
    using namespace std;
    const int MAXN = 105;
    int f[MAXN][MAXN];
    string s;
    int main()
    {
    	while (cin >> s)
    	{
    		if (s[0] == 'e') break;
    		memset(f, 0, sizeof(f));
    		
    		int N = s.size();
    		for (int len = 2; len <= N; len++)
    		{
    			for (int i = 0; i <= N - len; i++)	//枚举[0,1],[1,2]....[0,2],[1,3]....[0,3][1,4]....
    			{
    				int j = i + len - 1;
    				if ((s[i] == '(' && s[j] == ')') || (s[i] == '[' && s[j] == ']'))
    					f[i][j] =f[i+1][j-1]+ 2;
    				for (int k = i; k <= j - 1; k++)
    					f[i][j] = max(f[i][j], f[i][k] + f[k+1][j]);
    			}
    		}
    		cout << f[0][N - 1] << endl;
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    用JavaScript实现的将GB2312转换为UTF8编码
    一行内文本超出指定宽度溢出的处理
    JavaScript delete
    深入学习Enterprise Library for .NET Framework 2.0的Cache机制——分析篇
    CSS兼容技巧
    IE6,IE7,FF兼容CSS的差别及解决办法
    JavaScript获取当前文件全路径、当前目录、当前文件名
    DIV+CSS相对IE6 IE7和IE8兼容问题整理
    ie8兼容ie7css的方法和minheight的兼容问题
    Atitit.得到网络邻居列表java php c#.net python
  • 原文地址:https://www.cnblogs.com/qingoba/p/12995485.html
Copyright © 2020-2023  润新知