zoukankan      html  css  js  c++  java
  • codeforces 1272F dp+记录路径

    题意

    给出两个括号序列 (S)(T),让你构造一个最短的合法括号序列使 (S)(T) 是它的子序列。

    分析

    (dp[i][j][k]) 为这个最短的合法括号序列的前缀包含 (S) 的前 (i) 个字符,T的前 (j) 个字符且左括号的数量大于右括号的数量为 (k)时的长度。

    • 如果我们要添加一个左括号

      (dp[nexi][nexj][k+1]=min(dp[i][j][k]+1,dp[nexi][nexj][k+1]))

      (nexi) 为添加一个左括号后能匹配到的下一个 (i)(nexj) 为添加一个左括号能匹配到的下一个 (j)

    • 如果我们要添加一个右括号

      (dp[nexi][nexj][k-1]=min(dp[i][j][k]+1,dp[nexi][nexj][k-1]))

      (nexi) 为添加一个右括号后能匹配到的下一个 (i)(nexj) 为添加一个右括号能匹配到的下一个 (j)

    (dp) 过程中用一个数组记录下转移的前驱就可以倒推还原这个括号序列。

    Code

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define lson l,mid,p<<1
    #define rson mid+1,r,p<<1|1
    #define pb push_back
    #define ll long long
    using namespace std;
    const int inf=1e9;
    const int mod=1e9+7;
    const int maxn=2e2+10;
    char s[maxn],t[maxn];
    int n,m;
    int dp[maxn][maxn][2*maxn];
    struct ppo{
    	int x,y,k;
    	char c;
    }pre[maxn][maxn][2*maxn];
    int main(){
    	//ios::sync_with_stdio(false);
    	//freopen("in","r",stdin);
    	scanf("%s%s",s,t);
    	n=strlen(s);m=strlen(t);
    	for(int i=0;i<=n;i++) for(int j=0;j<=m;j++) for(int k=0;k<2*maxn;k++) dp[i][j][k]=inf;
    	dp[0][0][0]=0;
    	for(int i=0;i<=n;i++){
    		for(int j=0;j<=m;j++){
    			for(int k=0;k<2*maxn;k++){
    				if(dp[i][j][k]==inf) continue;
    				int x=i+(i<n&&s[i]=='(');
    				int y=j+(j<m&&t[j]=='(');
    				if(k+1<2*maxn&&dp[i][j][k]+1<dp[x][y][k+1]){
    					dp[x][y][k+1]=dp[i][j][k]+1;
    					pre[x][y][k+1]=ppo{i,j,k,'('};
    				}
    				x=i+(i<n&&s[i]==')');
    				y=j+(j<m&&t[j]==')');
    				if(k>0&&dp[i][j][k]+1<dp[x][y][k-1]){
    					dp[x][y][k-1]=dp[i][j][k]+1;
    					pre[x][y][k-1]=ppo{i,j,k,')'};
    				}
    			}
    		}
    	}
    	string str;
    	int x=n,y=m,k=0,p=0;
        for(int i=0;i<2*maxn;i++){
            if(dp[n][m][p]+p>dp[n][m][i]+i) p=i;
        }
        for(int i=0;i<p;i++) str.pb(')');
        k=p;
    	for(int i=0;i<dp[n][m][p];i++){
    		ppo p=pre[x][y][k];
    		str.pb(p.c);
    		x=p.x;y=p.y;k=p.k;
    	}
    	reverse(str.begin(), str.end());
    	cout<<str<<endl;
    	return 0;
    }
    
  • 相关阅读:
    查找质数的算法优化版
    一些新闻链接
    spring的自动装配基础
    Spring中的Autowired注解和Resource注解的区别
    动态规划:01背包 复习
    贪心问题 POJ 2393 Yogurt factory
    穷竭搜索:POJ 3187 Backward Digit Sums
    穷竭搜索: POJ 2718 Smallest Difference
    何凯文每日一句打卡||DAY1~DAY3
    贪心问题:区间覆盖 POJ 1328 Rader Installation
  • 原文地址:https://www.cnblogs.com/xyq0220/p/12061335.html
Copyright © 2011-2022 走看看