ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

区间dp

2022-05-18 13:31:06  阅读:177  来源: 互联网

标签:r1 int dfs 括号 l1 区间 dp


练习一下区间dp,总结一下题型

括号配对问题 Brackets Sequence


链接:https://172.16.79.125/contest/view.action?cid=831#problem/A

题意:给一串括号序列。依照合法括号的定义,加入若干括号,使得序列合法。

一道典题,思路是括号配对加上路径回溯,找出输入的所有不配对单括号,在输出时将其补充成完整括号对即可

括号配对

求序列配对的括号量,使用三层循环,前两层枚举长度和起点,然后要注意括号配对时更新dp值。由于合法的括号对都是嵌套或者并列的,所以第三层的枚举中间点只能帮我们解决括号的并列,但是不能解决括号的嵌套,所以我们还要自己加入判断,即当该区间的左右端点括号匹配时,dp[l][r]=dp[l+1][r-1]+1

路径回溯

这个也是典型,有两种方法,一种是不开辟数组,通过原来的dp转移方程来递归,另一种是开一个数组(一般dp过程可以简化数组维度,但路径回溯不可以,不过少部分题也可以),这个数组用来记录前驱(就是由谁更新了它),然后层层访问前驱即可。
以前写背包的路径回溯,两种方法都比较简单,现在看区间dp,感觉第二种好用点。区间dp由于第三层循环的存在,所以两种方法都会麻烦一点,第一种得遍历中间点,第二种得递归左区间和右区间。

代码:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

const int N = 1e2+10 , M = N<<1,mod=1e9+7;
typedef long long LL;
typedef pair<int,int> PII;
//#define x first 
//#define y second

//int h[N],e[M],ne[M],idx;
//
//void add(int a,int b)
//{
//	e[idx]=b,ne[idx]=h[a],h[a]=idx++;
//}

struct Node
{
	int l1,r1;
	int l2,r2;
};

char s[N];

int f[N][N];

Node path[N][N];

int st[N];

void dfs(int l,int r)    //路径回溯
{
	Node t =path[l][r];
	if(t.l1==l+1&&t.r1==r-1) 
	{
		st[l]=st[r]=1;
		dfs(l+1,r-1);
	}
	else if((t.l1|t.l2|t.r1|t.r2)==0) return;    //记得要加边界条件
	else 
	{
		dfs(t.l1,t.r1);
		dfs(t.l2,t.r2);
	}
}

int check(int l,int r)    //检查括号是否匹配
{
	if(s[l]=='('&&s[r]==')'||s[l]=='['&&s[r]==']') return 1;
	return 0;
}

void deal(char c)    //补全括号
{
	if(c=='('||c==')') cout<<"()";
	else if(c=='['||c==']') cout<<"[]";
}

void solve()        //区间dp
{
	cin>>s+1;
	int size=strlen(s+1);
	for(int len=2;len<=size;len++)
		for(int r=len;r<=size;r++)
		{
			int l=r-len+1;
			if(check(l,r))      //额外的判断条件
			{
				Node& t =path[l][r];
				if(f[l][r]<f[l+1][r-1]+1) f[l][r]=f[l+1][r-1]+1,t.l1=l+1,t.r1=r-1;
			}
			
			for(int k=l;k<r;k++)
			{
				Node& t =path[l][r];
				int sum=f[l][k]+f[k+1][r];
				if(sum>f[l][r]) 
				{
					f[l][r]=sum;
					t.l1=l,t.r1=k;
					t.l2=k+1,t.r2=r;
				}
			}
		}
	
	dfs(1,size);
	
	for(int i=1;i<=size;i++)
	{
		if(!st[i]) deal(s[i]);
		else cout<<s[i];
	}
	cout<<'\n';
	
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
//	int T;
//	cin>>T;
//	while(T--) 
	solve();
}

乡村邮局问题-Post Office(POJ-1160)

标签:r1,int,dfs,括号,l1,区间,dp
来源: https://www.cnblogs.com/Pleaf/p/16284346.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有