zjnu(1183)——括号序列【基础算法・动态规划】——高级
来源:互联网 发布:淘宝货源免费代理 编辑:程序博客网 时间:2024/05/18 16:16
首先,我只想声明一点,这道题有毒。。。我用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 111int 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;//!!!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 99999999int 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]);}
理解!!!举一反三!!加油!!!
- zjnu(1183)——括号序列【基础算法・动态规划】——高级
- zjnu(1175)——合唱队形【基础算法・动态规划】
- zjnu1181 石子合并【基础算法・动态规划】——高级
- 【动态规划】括号序列
- c++动态规划基础——最长上升子序列
- 动态规划算法——最长公共子序列求法
- 最长有序子序列—动态规划算法
- 最长有序子序列—动态规划算法
- 算法重拾之路——动态规划基础
- 动态规划——最长子序列
- 动态规划——最长非降子序列
- 动态规划——最大连乘子序列
- 动态规划——序列对准
- 算法——动态规划
- 算法——动态规划
- 算法——动态规划
- 算法——动态规划
- 算法——动态规划
- 为什么要使用SLF4J而不是Log4J
- OC-实例变量修饰符和纯私有变量
- 浅析PHP开发规范之性能优化
- 一个不错的博客
- 共享内存在Java中实现和应用
- zjnu(1183)——括号序列【基础算法・动态规划】——高级
- Swift 学习记录--2
- 性能测试技术提高的门槛
- STL priority_queue用法
- [c3p0] 第一篇:简单认识c3p0
- CRF++ 条件随机场使用
- Android进程管理详解
- java静态变量,静态方法,静态类
- 提高Linux系统应对短连接的负载能力的方法