• 1745. Yet Another Answer


    http://acm.timus.ru/problem.aspx?space=1&num=1745

    题目大意:

    可以是任意的顺序,在满足括号匹配的情况下,求组合成的字符串长度最长

    思路:

    先将每一个字符串进行处理,处理时将匹配的去掉 比如说  { )(()(())(} 处理后就变成了 {)(  (}

    当然字符串的长度是没有变化的 处理后的字符串假如说 左括号的个数为L 右括号的个数为R

    我们必须确定一个正确的顺序,可以让我们从头到尾的逐个决定是否选用当前字符串,而且不影响最优结果

    字符串有 L>R,L<R 和 L=R 三种情况,对于L>R的字符串要放在前面 因为每一个这样的字符串都可以使

    左括号 — 右括号 的值变大,

    而对于 L<R 的情况对应放在最后,L=R的情况放在中间

    对于L<R的字符串之间 需要把 R 小的放在前面, 对于L>R的情况 要用对称思想去确定顺序

    确定顺序之后,剩下的就DP就可以了

    代码:

    #include<iostream>
    #include<stack>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<set>
    #include<map>
    #include<string>
    #include<cmath>
    
    using namespace std;
    
    typedef long long ll;
    typedef pair<int,int> pp;
    const double eps=1e-9;
    const int INF=0x3f3f3f3f;
    const int N=1002;
    const int M=10002;
    struct node
    {
        string s;
        int lk,rk;
        int index;
    }x[N];
    int dp[N][M];
    int func(const node& a)
    {
        if(a.lk-a.rk>0) return 1;
        if(a.lk-a.rk<0) return -1;
        return 0;
    }
    bool cmp(const node& a,const node& b)
    {
        int lf=func(a),rf=func(b);
        if(lf==1&&rf==1)
        return a.rk<b.rk;
        if(lf==-1&&rf==-1)
        return a.lk>b.lk;
        return lf>rf;
    }
    int main()
    {
        //freopen("data.in","r",stdin);
        int n;
        while(cin>>n)
        {
            for(int i=0;i<n;++i)
            {
                cin>>x[i].s;
                x[i].index=i+1;
                stack<char>st;
                for(unsigned int j=0;j<x[i].s.size();++j)
                {
                    if(st.empty()||x[i].s[j]=='('||st.top()==')')
                    {
                        st.push(x[i].s[j]);
                    }else
                    {
                        st.pop();
                    }
                }
                x[i].lk=x[i].rk=0;
                while(!st.empty())
                {
                    if(st.top()=='(') ++x[i].lk;
                    else ++x[i].rk;
                    st.pop();
                }
            }
            sort(x,x+n,cmp);
    
            memset(dp,-1,sizeof(dp));
            dp[0][0]=0;
            for(int i=0;i<n;++i)
            {
                for(int j=0;j<M;++j)
                if(dp[i][j]!=-1)
                {
                    dp[i+1][j]=max(dp[i+1][j],dp[i][j]);
                    if(j>=x[i].rk)
                    dp[i+1][j-x[i].rk+x[i].lk]=max(dp[i+1][j-x[i].rk+x[i].lk],(int)(dp[i][j]+x[i].s.size()));
                }
            }
            vector<int>vt;
            int i=n,j=0;
            while(i>0)
            {
                if(dp[i-1][j]==dp[i][j])
                i=i-1;
                else
                {
                    vt.insert(vt.begin(),i-1);
                    j=j-x[i-1].lk+x[i-1].rk;i=i-1;
                }
            }
            cout<<dp[n][0]<<" "<<vt.size()<<endl;
            for(unsigned int i=0;i<vt.size();++i)
            {
                if(i>0) cout<<" ";
                cout<<x[vt[i]].index;
            }
            cout<<endl;
    
        }
        return 0;
    }
    
  • 相关阅读:
    JSON
    邮箱正则表达式
    聚聚科技---PHP开发笔试题及答案
    PHP字符串左边补0,字符串右边补0
    CSS3实现带阴影的弹球
    背景颜色渐变
    CSS3---滤镜
    CSS3裁剪与遮罩解析
    CSS3---混合模式
    使用CSS3制作各种形状
  • 原文地址:https://www.cnblogs.com/liulangye/p/3349523.html
Copyright © 2020-2023  润新知