• 南阳理工学院动态规划专题 括号问题2 总结


    南阳理工学院动态规划专题括号问题2总结

    这道题目初看起来很简单,但是我从看题到思考,到做题ac足足花了一个晚上加一个下午的时间,我也有到网上找代码的习惯,但是都是递归,特别蛋疼,我想用正统的动归去做,于是就开始了不一样的艰难探索之旅。

    分析过程:

    使用char str[1001]这个字符数组保存最初输入的括号序列,使用dp[1001][1001]这个数组保存中间结果,dp[i][j]的意思是从下标为i的字符到下标为j的字符的子问题最少要加多少个括号才能规范化。首先dp数组初始化为零,显然dp[i][i]=1;至于dp[i][i+1],str[i][i+1]配对的时候=0,当str[i][i+1]不配对的时候=2;到了这一步初始化工作结束。

    如果str[i]str[j]配对则分为两种情况:

    1.      i->(…)(…)<-j,dp[i][j]=min{dp[i][k]+dp[k+1][j]};

    2.      i->(..(..)..)<-j,dp[i][j]=dp[i+1][j-1],因为之前dp[i+1][j-1]已经计算过,因此直接使用即可。

    如果str[i]str[j]不配对分为四种情况:

    1.  str[i+1]str[j]的字串当中有与str[i]配对的括号,其对应的下标序列为k1,k2,k3,…

    dp[i][j]=min{dp[i][k1]+dp[k1+1][j], dp[i][k2]+dp[k2+1][j],dp[i][k3]+dp[k3+1][j],…};

    2.  当不存在与str[i]相匹配的括号时直接使用dp[i][j]=dp[i+1][j]+1;

    3.  str[i]str[j-1]的字串当中有与str[j]配对的括号,其对应的下标序列为k1,k2,k3,…

    dp[i][j]=min{dp[i][k1-1]+dp[k1][j], dp[i][k2-1]+dp[k2][j],dp[i][k3-1]+dp[k3][j],…};

    4.  不存在与str[i]相匹配的括号时直接使用dp[i][j]=dp[i][j-1]+1;

    计算完成后dp[0][strlen(str)-1]即是计算结果。

    Ac代码:

    #include<iostream>
    
    #include<stdio.h>
    
    #include<string.h>
    
    #define INF 100000000
    
    using namespace std;
    
    char str[101];
    
    int dp[101][101];
    
    bool match(char ch1,char ch2)
    
    {
    
       if(ch1=='('&&ch2==')')return true;
    
       if(ch1=='['&&ch2==']')return true;
    
       return false;
    
    }
    
    int main()
    
    {
    
       int cas;
    
       cin>>cas;
    
       while(cas--)
    
        {
    
          int top=-1;
    
          memset(str,0,sizeof(str));
    
          cin>>str;
    
         int l1=strlen(str);
    
         if(l1==0)
    
         {
    
             cout<<"0"<<endl;
    
             continue;
    
         }
    
         for(int i=0;i<l1;i++)dp[i][i]=1;
    
         for(int i=0;i<l1-1;i++)
    
         {
    
             if(match(str[i],str[i+1]))
    
             {
    
                  dp[i][i+1]=0;
    
             }
    
             else{dp[i][i+1]=2;}
    
         }
    
             for(int k=2;k<l1;k++)
    
             {
    
               for(int i=0;i+k<l1;i++)
    
               {
    
                  int j=i+k;
    
                  if(match(str[i],str[j]))
    
                  {
    
                     int min1=INF;
    
                     for(int kk=i+1;kk<j;kk++)
    
                     {
    
                         intt=dp[i][kk]+dp[kk+1][j];
    
                         if(min1>t)
    
                            min1=t;
    
                     }
    
                     int min2=dp[i+1][j-1];
    
                     dp[i][j]=min(min1,min2);
    
                  }
    
                  else
    
                  {
    
                      int min1=INF;
    
                      for(int kk=i+1;kk<j;kk++)
    
                      {
    
                          if(match(str[i],str[kk]))//检查左端
    
                          {
    
                              intt=dp[i][kk]+dp[kk+1][j];
    
                              if(min1>t)
    
                                 min1=t;
    
                          }
    
                      }
    
                      int min2=dp[i+1][j]+1;
    
                      int min3=IN
    
                      for(intkk=i+1;kk<j;kk++)//检查右端
    
                      {
    
                          if(match(str[kk],str[j]))
    
                          {
    
                              intt=dp[i][kk-1]+dp[kk][j];
    
                              if(min3>t)
    
                                min1=t;
    
                          }
    
                      }
    
                      int min4=dp[i][j-1]+1;
    
                     dp[i][j]=min(min(min1,min2),min(min3,min4));
    
                  }
    
             }
    
         }
    
         cout<<dp[0][l1-1]<<endl;
    
    //     for(int i=0;i<l1;i++)
    
    //     {
    
    //         for(int j=0;j<l1;j++)
    
    //         {
    
    //              cout<<dp[i][j]<<' ';
    
    //         }
    
    //         cout<<endl;
    
    //     }
    
     
    
        }
    
    }
    


     

    括号匹配(二)

    时间限制:1000 ms  | 内存限制:65535 KB

    难度:6

    描述

    给你一个字符串,里面只包含"(",")","[","]"四种符号,请问你需要至少添加多少个括号才能使这些括号匹配起来。
    如:
    []是匹配的
    ([])[]是匹配的
    ((]是不匹配的
    ([)]是不匹配的

    输入

    第一行输入一个正整数N,表示测试数据组数(N<=10)
    每组测试数据都只有一行,是一个字符串S,S中只包含以上所说的四种字符,S的长度不超过100

    输出

    对于每组测试数据都输出一个正整数,表示最少需要添加的括号的数量。每组测试输出占一行

    样例输入

    4

    []

    ([])[]

    ((]

    ([)]

    样例输出

    0

    0

    3

    2

    来源

    《算法艺术与信息学竞赛》

    上传者

    张云聪

     

     

  • 相关阅读:
    wpf中DataGrid自定义验证(包含BindingGroup)
    WPF博客地址分享
    ComboBox在WPF中的绑定示例:绑定项、集合、转换,及其源代码
    【windows phone】CollectionViewSource的妙用
    WPF之Binding深入探讨
    正确理解WPF中的TemplatedParent
    继续聊WPF——获取ComboBox中绑定的值
    WPF触发器(Trigger、DataTrigger、EventTrigger)
    jQuery和javaScript页面加载完成时触发的事件
    jQuery对象和dom对象的转换
  • 原文地址:https://www.cnblogs.com/jackwuyongxing/p/3366481.html
Copyright © 2020-2023  润新知