判定性动态规划

题目描述
给你一个合法的括号序列s和t,能否在s中删除若干对括号(或者不删除括号),使之变成序列t。

题目描述

第一行输入一个字符串s (2 ≤ |s| ≤ 100)
第二行输入一个字符串 t (2 ≤ |t| ≤ 100 )

输出描述

如果可以输出"Possible",否则输出"Impossible"

示例一
输入

(())
()

输出

Possible

示例二
输入

(()()())
((()))

输出

Impossible

示例三
输入

((())((())())())
(()(())())

输出

Possible

解题思路,区间dp版的判定性dp,第一次做哈,dp[i][j][k]代表s中前i个和t中前j个删去k个(删去左括号数量减去右括号数量)两个串是否匹配的集合,因为只能删左右配对的括号,最后求得就是dp[n][m][0]是否配对

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<vector>
#include<queue>
#include<set>
#define IL inline
#define x first
#define y second
typedef long long ll;
using namespace std;
const	int N=110;
int dp[N][N][N];
int main()
{
	char s1[N],s2[N];
	scanf("%s",s1+1);
	scanf("%s",s2+1);
//	cout<<n<<' '<<m<<endl;
	int n=strlen(s1+1);
	int m=strlen(s2+1);
	//cout<<n<<' '<<m<<endl;
	dp[0][0][0]=1;
	for(int i=0;i<n;i++)
	for(int j=0;j<m;j++)
	for(int k=0;k<n/2;k++)//为什么是n/2呢因为左括号最多有n/2个,每个串都是合法的
	{
		if(dp[i][j][k])
		{
		if(!k&&s1[i+1]==s2[j+1])		//为什么!k呢,k>0时例如s1:()((s2()( dp[3][2][1]=true  
		//		dp[4][3][1]就不是有效的了,要连续删掉2个‘(’
		dp[i+1][j+1][k]=1;
		if(s1[i+1]=='(')
		dp[i+1][j][k+1]=1;
		if(s1[i+1]==')'&&k>0)
		dp[i+1][j][k-1]=1;
		
		}
	}
	if(dp[n][m][0])
	cout<<"Possible"<<endl;
	else
	cout<<"Impossible"<<endl;
    return 0;
}




发布了230 篇原创文章 · 获赞 9 · 访问量 3711

猜你喜欢

转载自blog.csdn.net/qq_45961321/article/details/105375120
今日推荐