• poj1141Brackets Sequence 记忆化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],pre[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 = f(i+1,j-1);  //当两者恰好能组成一对括号时

          pre[i][j] = -1;

       }

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

       {

          if(ans>f(i,k)+f(k+1,j))

          {

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

             pre[i][j] = k;     //记录中间断开的点,递归打印括号

          }

       }

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

       return ans;

    }

    void print(int i,int j)

    {

       if(i>j)

          return;

       if(i==j)           //但两者相同位置时,直接输出该对括号

       {

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

             printf("()");

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

             printf("[]");

       }

       else if(pre[i][j]==-1)

       {     //当后面已有它匹配的串时,先输出该括号,再递归打印出中间的括号,再打印后面匹配的括号

          cout<<s[i];

          print(i+1,j-1);

          cout<<s[j];

       }

       else  //递归打印以k为分界的的括号

       {

          print(i,pre[i][j]);

          print(pre[i][j]+1,j);

       }

    }

    int main()

    {

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

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

       while(getline(cin,s))

       {

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

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

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

          {

             f(0,s.size()-1);

             print(0,s.size()-1);

             cout<<endl;

          }

          else

             cout<<endl;

       }

       return 0;

    }

  • 相关阅读:
    Linux读写执行权限对目录和文件的影响
    配置DNS服务安全加密传输遇到的问题
    如何将vim编辑器中的内容,按照列提取信息后,重新输入到文件中?
    虚拟机配置仅主机模式,无法ping通网关
    配置计划任务
    内存检测的脚本文件
    mount挂载的小问题:mount: no medium found on /dev/sr0
    名词解释
    电流、电压、功率的计算方式
    name 、 request_name 、 session_name 优先级
  • 原文地址:https://www.cnblogs.com/yejinru/p/2405783.html
Copyright © 2020-2023  润新知