zoukankan      html  css  js  c++  java
  • 最小添加括号数 dp记忆化

    题目:

    输入括号

    输入:(注意有空行,用getline()或者gets()输入)

    ([(]

    ([(((])))

    []]]]]

     

    )))(((

    要求输出最小要加入的括号数目

    分析:

       经典dp题,如果用dp自底向上的递推做的话,比较麻烦,其实用记忆化做很简单,

       每次递归前加上判断是否已经计算过即可减少计算量,相当于dfs里的剪枝,代码如下

     

    #include <iostream>

    #include <string>

    #include <cstring>

    using namespace std;

    #define X 205

    #define INF 1000

    int dp[X][X];

    string s;

    int f(int i,int j) //记忆化

    {

       if(dp[i][j]!=-1)            //当计算过时

          return dp[i][j];

       if(i>j)                     //当前面的指针大于后面的指针时,已经结束这次递归

          return 0;

       if(i==j)                 //恰巧相等时,加一

          return 1;

       int ans = INF;

       if((s[i]=='('&&s[j]==')')||(s[i]=='['&&s[j]==']'))

          ans = min(ans,f(i+1,j-1));  //当两者恰好能组成一对括号时

       else if(s[i]=='('||s[i]=='[')

          ans = min(ans,f(i+1,j)+1);  //当只有左边的一半时

       else if(s[j]==')'||s[j]==']')

          ans = min(ans,f(i,j-1)+1);  //当之有右边的一半时

       for(int k=i;k<j;k++)        //相当于最短路时的松弛操作

          ans = min(ans,f(i,k)+f(k+1,j));

       dp[i][j] = ans;             //用辅助数组储存状态,思想为用空间换取时间

       return ans;

    }

    int main()

    {

       freopen("sum.in","r",stdin);

       freopen("sum.out","w",stdout);

       while(getline(cin,s))

       {

          memset(dp,-1,sizeof(dp));

          if(s.size())    //注意到有空行

             cout<<f(0,s.size()-1)<<endl;

          else

             cout<<endl;

       }

       return 0;

    }

  • 相关阅读:
    散列函数的构造方法
    散列表(哈希表)查找
    散列表,哈希表,散列表查找法
    多路查找树之2-3-4树和B树
    多路查找树之2-3树的删除原理
    多路查找树之2-3树的插入原理
    多路查找树之2-3树
    字典:当索引不好用时2
    字典:当索引不好用时
    平衡二叉树的实现原理(代码实现)- 数据结构和算法78
  • 原文地址:https://www.cnblogs.com/yejinru/p/2405463.html
Copyright © 2011-2022 走看看