zjnu(1183)——括号序列【基础算法?动态规划】——高级

首先,我只想声明一点,这道题有毒。。。我用char读入就错了,然而换成string读入就对了或者可以把定义char的数组开的大一点,原先1A的一题硬是纠结了老半天。

传送门:zjnu

题意:

就是对于一个组成的序列,添加尽量少的括号得到一个规则序列,并且输出这个序列的长度。

不过我学到了两种定义dp状态的方法:

1)定义dp[i][j]为i~j中需要添加的最少的括号数。这里我们记录s为一段字符的开始位置,e为一段字符的结束位置。

①当(a[s]==‘(‘&&a[e]==‘)‘)||(a[s]==‘[‘&&a[e]==‘]‘)时,dp[s][e]=min(dp[s][e],dp[s+1][e-1]);

②当(a[s]==‘(‘&&a[e]!=‘)‘)||(a[s]==‘[‘&&a[e]!=‘]‘)时,dp[s][e]=min(dp[s][e],dp[s][e-1]+1);

③当(a[e]==‘)‘&&a[s]!=‘(‘)||(a[e]==‘]‘&&a[s]!=‘[‘)时,dp[s][e]=min(dp[s][e],dp[s+1][e]+1);

④然后当两个数中间还有其他数存在的时候,那么我们就用for,像石子归并那样,然后去更新dp[s][e]

最后输出的时候只要输出dp[0][len-1]+len就好了。

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define inf 99999999
#define maxn 111
int main(){
	string a;
	cin>>a;
	int l=a.length();
	int dp[111][111];
	for(int i=0;i<l;i++) dp[i][i]=1;
	for(int len=2;len<=l;len++){
		for(int s=0;s<=l-len;s++){
			int e=s+len-1;
			dp[s][e]=inf;<span style="white-space:pre">		</span>//!!!
			if((a[s]=='('&&a[e]==')')||(a[s]=='['&&a[e]==']'))
				dp[s][e]=min(dp[s][e],dp[s+1][e-1]);
			if((a[s]=='('&&a[e]!=')')||(a[s]=='['&&a[e]!=']'))
				dp[s][e]=min(dp[s][e],dp[s][e-1]+1);
			if((a[e]==')'&&a[s]!='(')||(a[e]==']'&&a[s]!='['))
				dp[s][e]=min(dp[s][e],dp[s+1][e]+1);
			for(int k=s;k<e;k++){
				dp[s][e]=min(dp[s][e],dp[s][k]+dp[k+1][e]);
			}
		}
	}
	printf("%d\n",dp[0][l-1]+l);
}

2)第二种状态定义的和第一种有点不一样。

定义dp[i][j]为i~j的区间内符合规范的字符串的最短的长度。

当然在这里我们需要进行初始化,对于不同位置的dp,我们需要进行不同的计算。(这里初始化是很重要的)

当a[s]==‘(‘&&a[e]==‘)‘时,那么dp[s][e]=dp[s+1][e-1]+2;

否则的话,则去寻找跳板,然后更新dp[s][e]。

其实主要的思路就是先算出小区间的每个最短的长度,然后再根据小区间然后去更新大区间的值。

最后输出的直接是dp[0][len-1]就可以了。

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define maxn 111
#define inf 99999999
int main(){
	string a;
	cin>>a;
	int dp[111][111];
	int len=a.length();
	for(int i=0;i<len;i++){
		for(int j=0;j<len;j++){
			if(i==j) dp[i][j]=2;
			if(i>j) dp[i][j]=0;
			else if(i<j) dp[i][j]=inf;
		}
	}
	for(int l=2;l<=len;l++){
		for(int s=0;s<=len-l;s++){
			int e=s+l-1;
			if((a[s]=='('&&a[e]==')')||(a[s]=='['&&a[e]==']')){
				if(l>2) dp[s][e]=dp[s+1][e-1]+2;
				else dp[s][e]=2;
			}
			for(int k=s;k<e;k++){
				dp[s][e]=min(dp[s][e],dp[s][k]+dp[k+1][e]);
			}
		}
	}
	printf("%d\n",dp[0][len-1]);
}

理解!!!举一反三!!加油!!!

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-15 16:09:37

zjnu(1183)——括号序列【基础算法?动态规划】——高级的相关文章

zjnu1181 石子合并【基础算法?动态规划】——高级

Description 在操场上沿一直线排列着 n堆石子.现要将石子有次序地合并成一堆.规定每次只能选相邻的两堆石子合并成新的一堆, 并将新的一堆石子数记为该次合并的得分.允许在第一次合并前对调一次相邻两堆石子的次序. 计算在上述条件下将n堆石子合并成一堆的最小得分. Input 输入数据共有二行,其中,第1行是石子堆数n≤100: 第2行是顺序排列的各堆石子数(≤20),每两个数之间用空格分隔. Output 输出合并的最小得分. Sample Input 3 2 5 1 Sample Out

百度的一道二面算法题分析:补全括号序列

算法题:补全括号序列 百度二面遇到的一个问题 大概意思就是 给出一个中括号序列,在序列前后可以加中括号字符,补全它... 当时没想起来解决办法,然后凉凉了,后来专门去搞了这道题,终于搞定 思路在注释里写的比较详细了,此处不再赘述(用了类似栈的思想) <?php /** * 字符串转数组 * @param $str string 输入的字符串 * @return array 转换之后的结果数组 */ function strToArray($str) { // 强制转换为字符串 $str = (s

【基础练习】【区间DP】codevs3657 括号序列题解

题目描述 Description 我们用以下规则定义一个合法的括号序列: (1)空序列是合法的 (2)假如S是一个合法的序列,则 (S) 和[S]都是合法的 (3)假如A 和 B 都是合法的,那么AB和BA也是合法的 例如以下是合法的括号序列: (), [], (()), ([]), ()[], ()[()] 以下是不合法括号序列的: (, [, ], )(, ([]), ([() 现在给定一些由'(', ')', '[', ,']'构成的序列 ,请添加尽量少的括号,得到一个合法的括号序列. 输

算法题:括号匹配(小中大括号序列)

括号序列由( )[ ]{ }组成,不合法的括号序列由( { ) },[ } { ],等等.编程实现一个函数,检查一个括号序列是否是合法的括号序列. 解法: 思路和"后缀表达式的求解"相似.我们借助栈,每读一个括号,如果是左括号,那么入栈,然后继续读下一个括号:如果是右括号,那么就要看看这个右括号和栈顶的括号是否匹配:如果匹配,那么弹出栈顶的括号,继续读下一个括号.当栈变空时,说明此括号序列是合法的. public class Test05 { public static boolean

有效的括号序列——算法面试刷题4(for google),考察stack

给定一个字符串所表示的括号序列,包含以下字符: '(', ')', '{', '}', '[' and ']', 判定是否是有效的括号序列. 括号必须依照 "()" 顺序表示, "()[]{}" 是有效的括号,但 "([)]" 则是无效的括号. 您在真实的面试中是否遇到过这个题? 样例 样例 1: 输入:"([)]" 输出:False 样例 2: 输入:"()[]{}" 输出:True 挑战 O(n)的时间

若干经典基础算法题目练习

练习1,判断是否为素数: // ConsoleAppIsPrime1.cpp : 定义控制台应用程序的入口点. // /* *函数功能:判断一个输入的数是否为素数 *函数原形:bool Prime( int x ) *参数:int x:将要判断的数 *返回值:bool型变量,判断是否是素数 *备注:需要包含头文件<math.h> *日期:2014/11/25 *原创:否 *作者:EbowTang *Email:[email protected] */ #include "stdafx

五大算法—动态规划

大常用算法之二:动态规划算法 一.基本概念 动态规划过程是:每次决策依赖于当前状态,又随即引起状态的转移.一个决策序列就是在变化的状态中产生出来的,所以,这种多阶段最优化决策解决问题的过程就称为动态规划. 二.基本思想与策略 基本思想与分治法类似,也是将待求解的问题分解为若干个子问题(阶段),按顺序求解子阶段,前一子问题的解,为后一子问题的求解提供了有用的信息.在求解任一子问题时,列出各种可能的局部解,通过决策保留那些有可能达到最优的局部解,丢弃其他局部解.依次解决各子问题,最后一个子问题就是初

有动态示意图!程序员必须知道的10大基础算法讲解

目录: 算法一:快速排序算法 算法二:堆排序算法 算法三:归并排序 算法四:二分查找算法 算法五:BFPRT(线性查找算法) 算法六:DFS(深度优先搜索) 算法七:BFS(广度优先搜索) 算法八:Dijkstra算法 算法九:动态规划算法 算法十:朴素贝叶斯分类算法 算法一:快速排序算法 快速排序是由东尼·霍尔所发展的一种排序算法.在平均状况下,排序 n 个项目要Ο(n log n)次比较.在最坏状况下则需要Ο(n2)次比较,但这种状况并不常见.事实上,快速排序通常明显比其他Ο(n log n

九章算法 基础算法 强化算法 系统设计 大数据 安卓 leetcode 高清视频

leetcode 直播视频讲座录像 九章算法视频录像,PPT 算法班,算法强化班,Java入门与基础算法班,big data项目实战班,Andriod项目实战班 九章算法下载 九章算法面试 九章算法leetcode 九章算法答案 九章算法mitbbs 九章算法班 九章算法ppt 九章算法录像 九章算法培训 九章算法微博 leetcode 视频 九章算法偷录 算法培训 算法班课程大纲: 1 从strStr谈面试技巧与Coding Style(免费试听) 2 二分搜索与旋转排序数组 Binary S